MongoDB聚合:在嵌套字段上使用$size

5
我将尝试执行一个棘手的聚合操作,以返回集合中文档内嵌数组的大小。
以下是重新创建样本数据的方法:
db.test.insert({
    projects: [
        {
            _id: 1,
            comments: [
                'a',
                'b',
                'c'
            ]
        },
        {
            _id: 2,
            comments: [
                'a',
                'b'
            ]
        },
        {
            _id: 3,
            comments: []
        }
    ]
})

我将执行的聚合操作在此处:
db.test.aggregate([
    // enter aggregation here
])

以下是期望的输出:

这里是期望得到的结果:

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

我在思考如何编写这段代码。如果我尝试以下代码:

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

结果将返回数组的大小:

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

如果我尝试像这样使用$map方法:

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

对于数组中的每个对象,它将返回一个类似于这样的数组:
[{
    projects: [
        {
            _id: 1,
            comment_count: [3, 2, 0]
        },
        {
            _id: 2,
            comment_count: [3, 2, 0]
        },
        {
            _id: 3,
            comment_count: [3, 2, 0]
        }
    ]
}]

感谢您的提前支持!

1
对于你的问题,我帮不上太多忙,但想说这是一个对于初学者来说措辞得当的好问题。 - Corbfon
2个回答

3

这里有一个使用$unwind$group以及$push$size的想法。最后使用$project来去除那个_id

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

您可以在这里查看结果

1
代码中只有一个错别字,他想要在"id"前加上连字符,所以$push命令内的代码应该是_id:" $projects._id"。 - Israel Zinc
我最终使用了这段代码的大部分。由于我的聚合管道要从多个上游集合中提取文档,因此我不得不放弃最后一个 $project 并在 $group 中构建我的最终输出,并使用 $$ROOT 引用顶层文档。谢谢! - jzkyburz

2
您需要在 $map聚合操作的in参数中指定每个字段,并最终使用$sizecomments数组一起使用。

类似于这样:

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

输出

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接