Search code examples
mongodbmongodb-queryaggregation-frameworkspring-data-mongodb

How to get length of sub array in mongo query


Below is the sample data:

db.infos.find()
{
    "groupId": "1111",
    "customerId": "A100",
    "tracks": [{
        "trackId": "234",
        "infos": [{
                "location": {
                    "address": "street1",
                    "city": "test",
                    "country": "US"
                }
            },
            {
                "location": {
                    "address": "street2",
                    "city": "test",
                    "country": "US"
                }
            },
            {
                "location": {
                    "address": "street3",
                    "city": "test",
                    "country": "US"
                }
            }
        ]
    }]
}
{
    "groupId": "2222",
    "customerId": "A100",
    "tracks": [{
        "trackId": "345",
        "infos": [{
                "location": {
                    "address": "street4",
                    "city": "test",
                    "country": "US"
                }
            },
            {
                "location": {
                    "address": "street5",
                    "city": "test",
                    "country": "US"
                }
            },
            {
                "location": {
                    "address": "street5",
                    "city": "test",
                    "country": "US"
                }
            }
        ]
    }]
}
{
    "groupId": "2222",
    "customerId": "A100",
    "tracks": [{
        "trackId": "666",
        "infos": [{
                "location": {
                    "address": "street4",
                    "city": "test",
                    "country": "US"
                }
            },
            {
                "location": {
                    "address": "street5",
                    "city": "test",
                    "country": "US"
                }
            },
            {
                "location": {
                    "address": "street5",
                    "city": "test",
                    "country": "US"
                }
            }
        ]
    }]
}

We need a query to get the length of "infos" sub array at groupId level. In the above sample data, we need the below output: 1111, 3 2222, 6

Tried below, but its not working:

 db.infos.aggregate([{"$project": {"groupId": "$groupId", "samples": "$tracks.infos"}}, {"$group": {"_id": "$groupId", "samples": {"$push": "$samples"}}}, {"$project": {"_id": 1, "samples": {"$size": "$samples"}}}], {   "allowDiskUse": true });

Also with large amount of data, above query is throwing an ExceededMemoryLimit exception:

2021-07-10T07:20:14.415+0000 E QUERY    [js] Error: command failed: {
    "ok" : 0,
    "errmsg" : "$push used too much memory and cannot spill to disk. Memory limit: 104857600 bytes",
    "code" : 146,
    "codeName" : "ExceededMemoryLimit"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:580:17
assert.commandWorked@src/mongo/shell/assert.js:673:16
DB.prototype._runAggregate@src/mongo/shell/db.js:260:9
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1074:12
@(shell):1:1

Solution

  • This should work with unwind:

    db.collection.aggregate([
      {
        $unwind: "$tracks"
      },
      {
        $group: {
          "_id": "$groupId",
          "count": {
            "$sum": {
              "$size": "$tracks.infos"
            }
          }
        }
      }
    ])
    

    Even if your tracks array has more than one object this will add them up. Playground