MongoDB: how to count number of keys in a document?

In Mongo (as in most NoSQL solutions) it's usually a good idea to pre-calculate such values if you want to do queries on them later (e.g. "where the number of different keys > 12") so maybe you should consider adding a new field "keyCount" which you increment every time a new key is added.


There's no built-in command for that. Fetch this document and count the keys yourself.


Quite possible if using MongoDB 3.6 and newer though the aggregation framework. Use the $objectToArray operator within an aggregation pipeline to convert the document to an array. The return array contains an element for each field/value pair in the original document. Each element in the return array is a document that contains two fields k and v.

The reference to root the document is made possible through the $$ROOT system variable which references the top-level document currently being processed in the aggregation pipeline stage.

On getting the array, you can then leverage the use of $addFields pipeline step to create a field that holds the counts and the actual count is derived with the use of the $size operator.

All this can be done in a single pipeline by nesting the expressions as follows:

db.collection.aggregate([
    { "$addFields": {
        "count": {
            "$size": { 
                "$objectToArray": "$$ROOT"
            }
        }
    } }     
])

Example Output

{
    "_id" : ObjectId("5a7cd94520a31e44e0e7e282"),
    "a" : 1.0,
    "b" : 1.0,
    "c" : 2.0,
    "z" : 2.0,
    "count" : 5
}

To exclude the _id field, you can use the $filter operator as:

db.collection.aggregate([
    {
        "$addFields": {
            "count": {
                "$size": { 
                    "$filter": {
                        "input": { "$objectToArray": "$$ROOT" },
                        "as": "el",
                        "cond": { "$ne": [ "$$el.k", "_id" ] }
                    }
                }
            }
        }
    }     
])

or as suggested by 0zkr PM simply add a $project pipeline step at the beginning:

db.collection.aggregate([
    { "$project": { "_id": 0 } },
    { "$addFields": {
        "count": {
            "$size": { 
                "$objectToArray": "$$ROOT"
            }
        }
    } }     
])

Tags:

Mongodb