简体   繁体   中英

MongoDB Aggregation $size on Nested Field

I'm trying to perform a tricky aggregation to return the size of a nested array within a document in the collection.

Here is how to re-create my sample data:

db.test.insert({
    projects: [
        {
            _id: 1,
            comments: [
                'a',
                'b',
                'c'
            ]
        },
        {
            _id: 2,
            comments: [
                'a',
                'b'
            ]
        },
        {
            _id: 3,
            comments: []
        }
    ]
})

The aggregation I would perform goes here:

db.test.aggregate([
    // enter aggregation here
])

Here is the desired output:

[{
    projects: [
        {
            _id: 1,
            comment_count: 3
        },
        {
            _id: 2,
            comment_count: 2
        },
        {
            _id: 3,
            comment_count: 0
        }
    ]
}]

I'm struggling with how to write this. If I try the following:

"projects.comment_count": {"$size": }

The result returns the size of the resulting array:

[{
    projects: [
        {
            _id: 1,
            comment_count: 3
        },
        {
            _id: 2,
            comment_count: 3
        },
        {
            _id: 3,
            comment_count: 3
        }
    ]
}]

If I try to use the $map method like this:

"projects.comment_count": { 
    "$map": { 
        "input": "$projects", 
        "as": "project", 
        "in": {
            "$size": "$$project.comments"
        } 
    } 
}

It will return an array that looks like this for each object in the array:

[{
    projects: [
        {
            _id: 1,
            comment_count: [3, 2, 0]
        },
        {
            _id: 2,
            comment_count: [3, 2, 0]
        },
        {
            _id: 3,
            comment_count: [3, 2, 0]
        }
    ]
}]

Thanks in advance!

Here is an idea using $unwind , $group and then $push with $size . Finally $project to get rid of that _id :

db.collection.aggregate([
  {
    "$unwind": "$projects"
  },
  {
    $group: {
      _id: null,
      "projects": {
        $push: {
          _id: "$projects._id",
          comment_count: {
            $size: "$projects.comments"
          }
        }
      }
    }
  },
  {
    "$project": {
      "_id": 0
    }
  }
])

You can see the result here

You need to specify each field inside the in argument of $map aggregation and finally use $size with the comments array.

Something like this

db.collection.aggregate([
  { "$project": {
    "projects": {
      "$map": {
        "input": "$projects",
        "in": {
          "_id": "$$this._id",
          "comment_count": {
            "$size": "$$this.comments"
          }
        }
      }
    }
  }}
])

Output

[
  {
    "projects": [
      {
        "_id": 1,
        "comment_count": 3
      },
      {
        "_id": 2,
        "comment_count": 2
      },
      {
        "_id": 3,
        "comment_count": 0
      }
    ]
  }
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM