的毗连字符串由
在我查询我想_id 这里同一项目合并成一个字符串组是我的文档的毗连字符串由
"_id" : ObjectId("59e955e633d64c81875bfd2f"),
"tag_id" : 1,
"client_id" : "10001"
"_id" : ObjectId("59e955e633d64c81875bfd30"),
"tag_id" : 1,
"client_id" : "10002"
我希望输出将
"_id" : 1
"client_id" : "10001,10002"
你可以做它将聚合框架作为“两步”操作。这是通过$push
先积累的项目到数组withing一个$group
管道,然后用$reduce
使用$concat
在最终投射所产生的阵列上:
db.collection.aggregate([
{ "$group": {
"_id": "$tag_id",
"client_id": { "$push": "$client_id" }
}},
{ "$addFields": {
"client_id": {
"$reduce": {
"input": "$client_id",
"initialValue": "",
"in": {
"$cond": {
"if": { "$eq": [ "$$value", "" ] },
"then": "$$this",
"else": {
"$concat": ["$$value", ",", "$$this"]
}
}
}
}
}
}}
])
我们也适用$cond
这里避免连接一个空字符串结果中带有逗号,因此它看起来更像是一个分隔列表。
FYI有一个JIRA问题SERVER-29339它不要求$reduce
被实现为accumulator expression,允许它在$group
流水线阶段直接使用。不太可能很快发生,但理论上它将取代上述中的$push
,并使操作成为单一管线阶段。示例建议的语法在JIRA问题上。
如果没有$reduce
做(需要的MongoDB 3.4),那么刚刚发布过程中的光标:
db.collection.aggregate([
{ "$group": {
"_id": "$tag_id",
"client_id": { "$push": "$client_id" }
}},
]).map(doc =>
Object.assign(
doc,
{ "client_id": doc.client_id.join(",") }
)
)
然后导致这样使用mapReduce
的其他选择,如果你真的必须:
db.collection.mapReduce(
function() {
emit(this.tag_id,this.client_id);
},
function(key,values) {
return [].concat.apply([],values.map(v => v.split(","))).join(",");
},
{ "out": { "inline": 1 } }
)
当然哪个输出mapReduce
形式的_id
和value
作为键集,但它基本上是输出。
我们使用[].concat.apply([],values.map(...))
,因为“减速器”的输出可以是“分隔字符串”,因为mapReduce
增量式工作,结果很大,因此减速器的输出可以在另一次传递时变成“输入”。所以我们需要期待这可以发生并相应地对待它。
谢谢,这真的很有用,我用mongo 3.4,因此第一个脚本完美地工作。 – shiyiwan
对于错字感到抱歉,它应该按tag_id – shiyiwan
@HassanImam分组几乎没有重复。这个问题特别要求“concat string”,这当然不是你所建议的副本显示的东西。 –
@NeilLunn我注意到它并删除了评论。 –