使用聚合合並字段
需求
有時候,我們需要在查詢結果中將某個字段(數組)合並起來,返回一個數組即可。
例子
假設集合user:
{
"_id" : ObjectId("5eb6bb5bc95fdd10d0f6d21e"),
"name" : "小明",
"education" : "本科",
"experiences" : [
{
"profession" : "程序員",
"ability" : [
"java",
"nodejs",
"golang"
]
}
]
}
// ----------------------------------------------
{
"_id" : ObjectId("5eb6bbdbc95fdd10d0f6d220"),
"name" : "小紅",
"education" : "本科",
"experiences" : [
{
"profession" : "銷售",
"ability" : [
"溝通",
"財務計算"
]
},
{
"profession" : "采購員",
"ability" : [
"英語",
"統計"
]
}
]
}
// ----------------------------------------------
{
"_id" : ObjectId("5eb6bdbbc95fdd10d0f6d23f"),
"name" : "小三",
"education" : "大專",
"experiences" : [
{
"profession" : "行政助理",
"ability" : [
"英語"
]
}
]
}
接下來我想查詢出所有學歷為“本科”的閱歷(experiences)列表,並把它們合並成一個數組返回,如:
{
"_id" : "1",
"experiences" : [
{ "profession" : "銷售", "ability" : ["溝通", "財務計算"] },
{ "profession" : "采購員", "ability" : ["英語", "統計"]},
{ "profession" : "程序員", "ability" : ["java", "nodejs", "golang"]}
]
}
實現
使用Aggregate來實現。
db.getCollection("user").aggregate(
[
{
"$match" : { "education" : "本科" }
},
{
"$group" : {
"_id" : "1",
"experiences" : {
"$addToSet" : "$experiences"
}
}
},
{
"$project" : {
"experiences" : {
"$reduce" : {
"input" : "$experiences",
"initialValue" : [],
"in" : { "$concatArrays" : ["$$value", "$$this"] }
}
}
}
}
]
);
說明:
- $match: 選擇器,篩選的條件,這里查詢出學歷(education)為本科的數據。
- $group: 相當於sql中的group by, 例子中的"_id"只是用於分組的標識,“experiences“設置分組返回到哪個字段上,相當於as。
- $addToSet: 不重復添加到數組。
到這里,會把學歷為“本科”的閱歷全部查出來,數據是這樣子:
{
"_id" : "1",
"experiences" : [
[
{"profession" : "銷售", "ability" : [ "溝通", "財務計算" ]},
{"profession" : "采購員", "ability" : [ "英語", "統計" ]}
],
[
{"profession" : "程序員", "ability" : ["java", "nodejs", "golang"]}
]
]
}
但這還不是我們要的結果,使用$project再次處理,所有experiences追加
。
{
"$project" : {
"experiences" : {
"$reduce" : {
"input" : "$experiences",
"initialValue" : [],
"in" : { "$concatArrays" : ["$$value", "$$this"] }
}
}
}
}
說明:
- $project: 接受一個文檔,該文檔可以指定包含字段、禁止顯示id字段、添加新字段以及重置現有字段的值。或者,可以指定排除字段。
- $reduce:將"in"里的表達式應用到"input"數組里,並將它們合並成一個數組。
- "in"里面的表達式可以很靈活的對數組操作,這里用的$concatArrays將experiences[]字段里的元素連接起來。
最后結果:
{
"_id" : "1",
"experiences" : [
{ "profession" : "銷售", "ability" : ["溝通", "財務計算"] },
{ "profession" : "采購員", "ability" : ["英語", "統計"]},
{ "profession" : "程序員", "ability" : ["java", "nodejs", "golang"]}
]
}
參考
https://docs.mongodb.com/manual/reference/operator/aggregation/reduce/
(完)