Count how many times is the same value present in array

时间:2016-10-20 12:50:40

标签: mongodb mongodb-query aggregation-framework

After grouping in aggregation I have elements that look the following way:

{_id: ID, items: ["yes", "no", "yes", "no", "no", "yes", "no", "no", "no"]}

I'd like to project how many times is certain value present in items array

To end up with a document in the format of:

{_id: ID, yes: 3, no: 6}

3 个答案:

答案 0 :(得分:2)

Use a combination of $filter and $size operators to filter the items array based on a given condition and return the count respectively. For example, run the following pipeline to get the desired result. Of course this assumes the distinct binary elements from the items list "yes" and "no" are known beforehand:

db.collection.aggregate([
    {
        "$project": {
            "yes": {
                "$size": {
                    "$filter": {
                        "input": "$items",
                        "as": "item",
                        "cond": {
                            "$eq": ["$$item", "yes"]
                        }
                    }
                }
            },
            "no": {
                "$size": {
                    "$filter": {
                        "input": "$items",
                        "as": "item",
                        "cond": {
                            "$eq": ["$$item", "no"]
                        }
                    }
                }
            }
        }
    }
])

For a solution where the distinct elements are not known in advance, then you would need to $unwind the items array, group the flattened documents and aggregate the counts as:

db.collection.aggregate([
    { "$unwind": "$items" },
    {
        "$group": {
            "_id": "$items",
            "id": { "$first": "$_id" },
            "count": { "$sum": 1 }
        }
    },
    {
        "$group": {
            "_id": "$id",
            "counts": {
                "$push": {
                    "item": "$_id",
                    "count": "$count"
                }
            }
        }
    }
])

Sample Output

{
    "_id" : ID,
    "counts" : [ 
        {
            "item" : "yes",
            "count" : 3
        }, 
        {
            "item" : "no",
            "count" : 6
        }
    ]
}

答案 1 :(得分:0)

You could add two more phase to your aggregation pipeline

{ $unwind: '$items' }

Then group by items again,

{ $group: { _id: '$items', count: { $sum: 1 }}}

This will generates an array like:

[{ _id: 'yes', count: 3}, { _id: 'no', count: 6}]

答案 2 :(得分:0)

db.collection.aggregate([ 
  "$project" : {
    _id : 1,
    "yes" : {
      $size : {
        "$map" : {
          input : "$items",
          as : "Yes",
          in : {"$eq" : ["$$Yes","yes"]}
        }
      }
    }
    "no" : {
      "$size" : {          
        "$map" : {
          input : "$items",
          as : "No",
          in : {"$eq" : ["$$No","no"]}
        }
      }
    }
  }
])