【发布时间】:2020-07-11 14:52:38
【问题描述】:
经过一些聚合管道阶段后,我的 MongoDB 文档具有以下格式(示例):
{
"data": [
{
"_id": "group1",
"start": [
"a",
"b",
"c"
],
"end": [
"l",
"m",
"n",
"o"
],
"mid": [
"a1",
"a2",
"a3",
"a4"
]
},
{
"_id": "group2",
"start": [
"p",
"q",
"r",
"s"
],
"end": [
"h",
"i",
"j"
],
"mid": [
"b1",
"b2",
"b3"
]
}
]
}
我需要将我的数据转换成以下格式:
{
"new_data": [
{
"_id": "group1",
"val": [
{
"start": "a",
"end": "l"
},
{
"start": "b",
"end": "m"
},
{
"start": "c",
"end": "n"
},
{
"start": "a4",
"end": "o"
}
]
},
{
"_id": "group2",
"val": [
{
"start": "p",
"end": "h"
},
{
"start": "q",
"end": "i"
},
{
"start": "r",
"end": "j"
},
{
"start": "s",
"end": "default value"
}
]
}
]
}
问题: 特殊情况如何处理?
在转置 start 和 end 数组时,
- 如果
start的第n个值为NULL,则取mid数组中的第n个值作为start值 - 如果
end的第n个值为NULL,则使用一些“默认值”作为end值(这部分有解决方案)
mid的长度 =end的长度
这是我尝试过的:
db.collection.aggregate([
{
..... some pipeline stages
},
{
$unwind:
{path:"$data"}
},
{
"$project": {
"data.mid":1,
"data._id":1,
"val": {
"$map": {
"input": {
"$objectToArray": {
"$arrayToObject": {
"$zip": {
"inputs": [
"$data.start","$data.end"],
useLongestLength: true,
defaults: [ *I don't know what to write here*, "default value"] // Need help
}
}
}
},
"as": "el",
"in": {
"start": "$$el.k",
"end": "$$el.v"
}
}
}
}
},
{ "$group": {
"_id": "$data._id",
"new_data": {
"$push": { "transformed_data":"$val" }
}
}}
]).pretty()
如何实现这个用例?
【问题讨论】:
-
我认为
$zip只允许一个默认值,所以如果长度差大于一个,您将使用mid中的哪个值,例如start: ["a"], end: ["x", "y", "z"], mid: ["j", "k", "l"]。或者如果mid的长度比end短,例如mid: ["j"]或mid: ["j", "k"] -
如果
start: ["a"]、end: ["x", "y", "z"]、mid: ["j", "k", "l"]:那么val:[{ "start": "a","end": "x" },{"start": "k","end": "y" },{"start": "l","end": "z" }]在我的情况下长度为mid=长度为end。这个用例可以使用 mongoDB 管道实现吗? -
在聚合的最后阶段,您按
$data._id分组,我认为这会将"group1"和"group2"的2 个文档输出为_id,但您只想作为输出一个包含数组newData的文档。那么在最后阶段你真正想用什么来分组呢? -
其实两者都适合我。
标签: mongodb mongodb-query aggregation-framework