的毗连字符串由

问题描述:

集团

在我查询我想_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" 
+0

对于错字感到抱歉,它应该按tag_id – shiyiwan

+0

@HassanImam分组几乎没有重复。这个问题特别要求“concat string”,这当然不是你所建议的副本显示的东西。 –

+0

@NeilLunn我注意到它并删除了评论。 –

你可以做它将聚合框架作为“两步”操作。这是通过$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形式的_idvalue作为键集,但它基本上是输出。

我们使用[].concat.apply([],values.map(...)),因为“减速器”的输出可以是“分隔字符串”,因为mapReduce增量式工作,结果很大,因此减速器的输出可以在另一次传递时变成“输入”。所以我们需要期待这可以发生并相应地对待它。

+0

谢谢,这真的很有用,我用mongo 3.4,因此第一个脚本完美地工作。 – shiyiwan