我有一个聚合管道,我试图在其中查找数组属性中的唯一值以及每个文档数组中每个值的实例数。
我到达了文档如下所示的阶段:
{
_id: ObjectId("5d8cac657d2d1e0145268fb4"),
values: [
"5d8a2c3d4768d9660d3ba383",
"5d8a1d4f4768d951cb6c8989"
]
},
{
_id: ObjectId("5d8caf4039321e7b14061a46"),
values: [
"5d8a2c3d4768d9660d3ba383",
"5d8c835a39321e7b15792353"
]
}
从这里我希望得到如下结果:
{
values: {
"5d8a2c3d4768d9660d3ba383": 2,
"5d8a1d4f4768d951cb6c8989": 1,
"5d8c835a39321e7b15792353" : 1
}
}
or
{
values: [
{ "id": "5d8a2c3d4768d9660d3ba383", "count" : 2 },
{ "id": "5d8a1d4f4768d951cb6c8989", "count" : 1 },
{ "id": "5d8c835a39321e7b15792353", "count" : 1 }
]
}
我不太关心结果的格式,只要我有唯一的值和它们的计数,我就可以使用它 - 无论最高效的方法是什么都可以。我可以通过使用带有 $push 和 $reduce 的 $group 阶段来获取唯一值,但我无法以这种方式获取计数 - 有人可以指出我正确的方向吗?
如果您想要第一个选项,您可以尝试以下查询:
$unwind
数组values
能够单独获取每个元素。$group
获取每个元素的计数。_id
作为 null
将所有值放入一个数组中。这里的每个元素都是一个具有 k
和 v
属性的对象。这将在下一阶段使用。$project
,不输出_id
值(位于null
中)并使用$arrayToObject。在上一阶段使用 k
和 v
创建了一个数组,其中的对象可有效转换为所需的对象。db.collection.aggregate([
{
"$unwind": "$values"
},
{
"$group": {
"_id": "$values",
"count": {
"$sum": 1
}
}
},
{
"$group": {
"_id": null,
"values": {
"$push": {
"k": "$_id",
"v": "$count"
}
}
}
},
{
"$project": {
"_id": 0,
"values": {
"$arrayToObject": "$values"
}
}
}
])
示例这里
对于第二个选项,您可以尝试以下查询:
$$ROOT
来获取整个对象。由于这里不需要任何其他内容,您可以按原样设置对象。$project
,不输出_id
值。db.collection.aggregate([
{
"$unwind": "$values"
},
{
"$group": {
"_id": "$values",
"count": {
"$sum": 1
}
}
},
{
"$group": {
"_id": null,
"values": {
"$push": "$$ROOT"
}
}
},
{
"$project": {
"_id": 0
}
}
])
示例这里
编辑:我没有注意到第二个例子有
id
而不是 _id
。如果相关,您可以使用 this query 代替,这是相同的,但不是使用 $$ROOT
来设置整个对象,而是创建 id/count
对象。