我的文档结构如下:
mode: "b",
a: [0,1,2],
b: [1,4,5],
c: [2,2]
我想要投射等于mode
的字段。最终结果应该是:
data: [1,4,5] // since mode == "b", it returns b's value
我试过$$CURRENT[$mode]
,但看起来你不能在mongo中使用这样的括号。我尝试使用像这样的局部变量:
$let: {
vars: {mode: "$mode"},
in: "$$CURRENT.$$mode"
}
但这也不起作用。我正在考虑使用$switch
,然后手动输入所有可能的模式。但我想知道是否有更好的方法来做到这一点。
答案 0 :(得分:1)
您正在寻找错误的地方,但是如果您可以使用$switch
那么您拥有MongoDB 3.4并且您可以使用$objectToArray
这实际上是正确的事情。你的问题是你正在尝试动态地"通过"值"来指代一个财产。它的关键名称"。你不能这样做,所以$objectToArray
制作"键" a"值"
所以给你的文件:
{ "mode": "a", "a": [0,1,2], "b": [1,4,5], "c": [2,2] }
然后使用$map
和$filter
进行聚合,将转换后的元素作为数组使用:
db.sample.aggregate([
{ "$project": {
"_id": 0,
"mode": 1,
"data": {
"$arrayElemAt": [
{ "$map": {
"input": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"cond": { "$eq": ["$$this.k","$mode"] }
}
},
"in": "$$this.v"
}},
0
]
}
}}
])
或者使用$let
和$indexOfArray
,如果这对您来说更合理:
db.sample.aggregate([
{ "$project": {
"_id": 0,
"mode": 1,
"data": {
"$let": {
"vars": { "doc": { "$objectToArray": "$$ROOT" } },
"in": {
"$arrayElemAt": [
"$$doc.v",
{ "$indexOfArray": [ "$$doc.k", "$mode" ] }
]
}
}
}
}}
])
与所选字段匹配:
{
"mode" : "a",
"data" : [
0.0,
1.0,
2.0
]
}
如果你看"只是" $objectToArray
在这里做了什么,原因应该是不言而喻的:
{
"data" : [
{
"k" : "_id",
"v" : ObjectId("597915787dcd6a5f6a9b4b98")
},
{
"k" : "mode",
"v" : "a"
},
{
"k" : "a",
"v" : [
0.0,
1.0,
2.0
]
},
{
"k" : "b",
"v" : [
1.0,
4.0,
5.0
]
},
{
"k" : "c",
"v" : [
2.0,
2.0
]
}
]
}
所以现在而不是有一个"对象"使用命名属性,"数组"始终包含"k"
,命名为"键"和"v"
包含"值"。这很容易$filter
并获得所需的结果,或者基本上使用任何与数组一起使用的方法来获得匹配。