MongoDB $size

In MongoDB, the $size aggregation pipeline operator counts and returns the total number of items in an array.

The $size operator accepts one argument. The argument can be any valid expression that resolves to an array.

Example

Suppose we have a collection called test with the following documents:

{ "_id" : 1, "data" : [ ] }
{ "_id" : 2, "data" : [ "a" ] }
{ "_id" : 3, "data" : [ "a", "b" ] }
{ "_id" : 4, "data" : [ "a", "b", "c" ] }
{ "_id" : 5, "data" : [ 1, 1, 1, 1 ] }

We can use $size to return the number of items in the arrays in the respective data fields.

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 1, 2, 3, 4, 5 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $size: [ "$data" ] }
          }
     }
   ]
)

Result:

{ "data" : [ ], "result" : 0 }
{ "data" : [ "a" ], "result" : 1 }
{ "data" : [ "a", "b" ], "result" : 2 }
{ "data" : [ "a", "b", "c" ], "result" : 3 }
{ "data" : [ 1, 1, 1, 1 ], "result" : 4 }

Nested Arrays

The $size operator does not descend into nested arrays and count their elements. It evaluates the array from the top level.

Suppose we have the following document in our collection:

{ "data" : [ [ 1, 2 ], 3 ], "result" : 2 }

And we apply $size to that:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 6 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $size: [ "$data" ] }
          }
     }
   ]
)

Result:

{ "data" : [ [ 1, 2 ], 3 ], "result" : 2 }

The nested array is counted as one element (regardless of how many elements it contains).

Wrong Data Types

The argument can be any valid expression, as long as it resolves to an array. If it doesn’t resolve to an array, an error is produced.

Suppose we have the following document:

{ "_id" : 7, "data" : 3 }

The data field does not resolve to an array.

Here’s what happens when we apply $size to that field:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 7 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $size: [ "$data" ] }
          }
     }
   ]
)

Result:

Error: command failed: {
	"ok" : 0,
	"errmsg" : "The argument to $size must be an array, but was of type: double",
	"code" : 17124,
	"codeName" : "Location17124"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1

The error message tells us that The argument to $size must be an array, but was of type: double.

Missing Fields

If the field doesn’t exist in the document, an error is returned.

Suppose we have the following document:

{ "_id" : 8 }

And we apply $size to that document:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 8 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $size: [ "$data" ] }
          }
     }
   ]
)

Result:

Error: command failed: {
	"ok" : 0,
	"errmsg" : "The argument to $size must be an array, but was of type: missing",
	"code" : 17124,
	"codeName" : "Location17124"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1