Anda dapat melakukannya dengan kerangka kerja agregasi sebagai operasi "dua langkah". Yang pertama mengumpulkan item ke array melalui $push
dengan $group
pipeline, lalu menggunakan $concat
dengan $reduce
pada larik yang dihasilkan dalam proyeksi akhir:
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"]
}
}
}
}
}
}}
])
Kami juga menerapkan $cond
di sini untuk menghindari penggabungan string kosong dengan koma di hasil, sehingga lebih terlihat seperti daftar yang dibatasi.
FYI Ada masalah JIRA SERVER-29339
yang meminta $reduce
untuk diimplementasikan sebagai ekspresi akumulator
untuk mengizinkannya digunakan secara langsung di $group
tahap pipa. Kemungkinan tidak akan terjadi dalam waktu dekat, tetapi secara teoritis akan menggantikan $push
di atas dan membuat operasi satu tahap pipa. Contoh sintaks yang diusulkan ada di edisi JIRA.
Jika Anda tidak memiliki $reduce
( membutuhkan MongoDB 3.4 ) lalu cukup posting proses kursor:
db.collection.aggregate([
{ "$group": {
"_id": "$tag_id",
"client_id": { "$push": "$client_id" }
}},
]).map( doc =>
Object.assign(
doc,
{ "client_id": doc.client_id.join(",") }
)
)
Yang kemudian mengarah ke alternatif lain untuk melakukan ini menggunakan mapReduce
jika Anda benar-benar harus:
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 } }
)
Yang tentu saja menghasilkan mapReduce
tertentu bentuk _id
dan value
sebagai set kunci, tetapi pada dasarnya adalah output.
Kami menggunakan [].concat.apply([],values.map(...))
karena output dari "reducer" bisa berupa "delimited string" karena mapReduce
bekerja secara bertahap dengan hasil yang besar dan oleh karena itu keluaran dari peredam dapat menjadi "masukan" pada lintasan lain. Jadi kita perlu berharap bahwa ini bisa terjadi dan memperlakukannya dengan semestinya.