你可以做它將聚合框架作爲「兩步」操作。這是通過$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
增量式工作,結果很大,因此減速器的輸出可以在另一次傳遞時變成「輸入」。所以我們需要期待這可以發生並相應地對待它。
對於錯字感到抱歉,它應該按tag_id – shiyiwan
@HassanImam分組幾乎沒有重複。這個問題特別要求「concat string」,這當然不是你所建議的副本顯示的東西。 –
@NeilLunn我注意到它並刪除了評論。 –