我有一篇文章集:
{
_id: 9999,
authorId: 12345,
coAuthors: [23456,34567],
title: 'My Article'
},
{
_id: 10000,
authorId: 78910,
title: 'My Second Article'
}
我正在试图找出如何从数据库中获取不同作者和共同作者ID的列表。我尝试过push
,concat
和addToSet
,但似乎找不到合适的组合。我在2.4.6上,所以我无法访问setUnion
。
答案 0 :(得分:1)
虽然$setUnion
将成为"理想的"做到这一点的方法,还有另一种基本上涉及"切换"在"类型"之间交替选择哪个领域:
db.collection.aggregate([
{ "$project": {
"authorId": 1,
"coAuthors": { "$ifNull": [ "$coAuthors", [null] ] },
"type": { "$const": [ true,false ] }
}},
{ "$unwind": "$coAuthors" },
{ "$unwind": "$type" },
{ "$group": {
"_id": {
"$cond": [
"$type",
"$authorId",
"$coAuthors"
]
}
}},
{ "$match": { "_id": { "$ne": null } } }
])
就是这样。您可能会将$const
操作知道为MongoDB 2.6中的$literal
运算符。它一直存在,但只是记录在案并给出了别名"在2.6发布。
当然,两种情况下的$unwind
操作都会产生更多的副本和#34;数据,但这是" distinct"价值所以没关系。只需依赖于预测"类型的true/false
交替值"字段(一旦解开)你只需交替选择字段。
这个小mapReduce也做了同样的事情:
db.collection.mapReduce(
function() {
emit(this.authorId,null);
if ( this.hasOwnProperty("coAuthors"))
this.coAuthors.forEach(function(id) {
emit(id,null);
});
},
function(key,values) {
return null;
},
{ "out": { "inline": 1 } }
)
为了记录,$setUnion
当然要更清洁,更高效:
db.collection.aggregate([
{ "$project": {
"combined": {
"$setUnion": [
{ "$map": {
"input": ["A"],
"as": "el",
"in": "$authorId"
}},
{ "$ifNull": [ "$coAuthors", [] ] }
]
}
}},
{ "$unwind": "$combined" },
{ "$group": {
"_id": "$combined"
}}
])
所以唯一真正的问题是转换单数" authorId"通过$map
到一个数组并在一个空数组中输入" coAuthors"字段不在文档中。
两者都从示例文档中输出相同的不同值:
{ "_id" : 78910 }
{ "_id" : 23456 }
{ "_id" : 34567 }
{ "_id" : 12345 }