我有一个相当简单的任务我想使用MongoDB的聚合管道来实现。我想将一个字段中的数组视为集合(即忽略顺序和重复),并按它们分组。例如,集合可能是:
[
{
_id: 1
names: ["a", "b"]
},
{
_id: 2
names: ["c", "a"]
},
{
_id: 3
names: ["b", "a"]
}
]
我想要的结果是:
[
{
names: ["a", "b"],
count: 2
},
{
names: ["a", "c"],
count: 1
}
]
谢谢!
答案 0 :(得分:1)
您需要$sort
结果才能使其与分组键保持一致。真的没有别的办法:
db.collection.aggregate([
{ "$unwind": "$names" },
{ "$sort": { "_id": 1, "names": 1} },
{ "$group": {
"_id": "$_id",
"names": { "$push": "$names" }
}},
{ "$group": {
"_id": "$names",
"count": { "$sum": 1 }
}}
])
就像你问的那样回报:
[
{
"_id": ["a", "b"],
"count": 2
},
{
"_id": ["a", "c"],
"count": 1
}
]
虽然有很多运算符像“集合”那样处理数组,但是没有一个运算符将数组内容“重新排序”为一种在分组时应用的一致方式。只有在$sort
时才会这样做。
即使数组包含“重复”,并且应用了一些设置转换,它们仍然没有按顺序排列:
db.testa.insert_many([
{ "a" : [ "a", "b" ] },
{ "a" : [ "b", "a" ] },
{ "a" : [ "b", "a", "a" ] }
])
db.testa.aggregate({ "$project": { "_id": 0, "a": { "$setUnion": [ "$a", [] ] } } })
该样本当然会返回:
{ "a" : [ "b", "a" ] }
{ "a" : [ "a", "b" ] }
{ "a" : [ "a", "b" ] }
因此,您仍然需要$unwind
和$sort
才能获得用于分组目的的一致“设置”。
答案 1 :(得分:1)
您可以通过将多个聚合管道拼接在一起来获得结果。
db.collection.aggregate([
{$unwind:"$names"},
{$sort:{_id:1, names:1}},
{$group:{_id:"$_id", names:{$push:"$names"}}},
{$group:{_id:"$names", count:{$sum:1}}},
{$project:{_id:0, names:"$_id", count:1}}
])
它发出:
{
"count" : NumberInt(1),
"names" : [
"a",
"c"
]
}
{
"count" : NumberInt(2),
"names" : [
"a",
"b"
]
}