问题
I want to find all zone data with "AHU":"C". First, I query without projection and get these.
> db.buildings.find({"zone.AHU": "C"}).pretty()
{
"_id" : ObjectId("5aba4460a042dc4a2fdf26cd"),
"name" : "Test Street",
"coordinate" : [
12,
31
],
"yearlyEnergyCost" : 1444,
"zone" : [
{
"name" : "AHU-C-Z2",
"_id" : ObjectId("5aba4460a042dc4a2fdf26ce"),
"AHU" : "C",
"precooling" : [ ],
"subZone" : [ ]
},
{
"name" : "AHU-D-Z1",
"_id" : ObjectId("5abc7528100730697163a3ab"),
"AHU" : "D",
"precooling" : [ ],
"subZone" : [ ]
},
{
"name" : "AHU-C-Z1",
"AHU" : "C",
"_id" : ObjectId("5ac09c898249affa03506eff"),
"precooling" : [ ],
"subZone" : [ ]
},
{
"name" : "AHU-C-Z3",
"AHU" : "C",
"_id" : ObjectId("5ac09c898249affa03506efe"),
"precooling" : [ ],
"subZone" : [ ]
}
],
"__v" : 2
}
However, when I use $elemMatch, it only returns the first zone element with "AHU":"C"
> db.buildings.find({"zone.AHU": "C"}, {_id: 0, zone: {$elemMatch: {AHU: "C"}}}).pretty()
{
"zone" : [
{
"name" : "AHU-C-Z2",
"_id" : ObjectId("5aba4460a042dc4a2fdf26ce"),
"AHU" : "C",
"precooling" : [ ],
"subZone" : [ ]
}
]
}
From the doc, I realised that $elemMatch (projection) only retrieve the first one, but how can I retrieve all corresponded (AHU-C-Z1, AHU-C-Z2, AHU-C-Z3)? Thanks.
This is the collection:
{
"_id":{
"$oid":"5aa65bc96996e045104116e7"
},
"name":"Talker Street",
"coordinate":[
11.82,
-9.26
],
"yearlyEnergyCost":100,
"zone":[
{
"name":"AHU-B-Z1",
"_id":{
"$oid":"5aa65bc96996e045104116e8"
},
"precooling":[
{
"_id":{
"$oid":"5aa73a7d2f991a657fd52c7e"
},
"resultPrecool":{
"$oid":"5aa73a7d2f991a657fd52b5d"
},
"dateRun":{
"$date":"2018-03-14T00:00:00.000+0000"
},
"lastUpdated":{
"$date":"2018-03-13T02:41:02.086+0000"
}
}
]
},
{
"name":"AHU-B-Z2",
"_id":{
"$oid":"5aa9f1f8131e6412c17d71d3"
},
"precooling":[
]
},
{
"name":"AHU-B-Z3",
"_id":{
"$oid":"5aa9f1f8131e6412c17d71d2"
},
"precooling":[
]
}
],
"__v":19
}{
"_id":{
"$oid":"5aba4460a042dc4a2fdf26cd"
},
"name":"Test Street",
"coordinate":[
12,
31
],
"yearlyEnergyCost":1444,
"zone":[
{
"name":"AHU-C-Z2",
"_id":{
"$oid":"5aba4460a042dc4a2fdf26ce"
},
"AHU":"C",
"precooling":[
],
"subZone":[
]
},
{
"name":"AHU-D-Z1",
"_id":{
"$oid":"5abc7528100730697163a3ab"
},
"AHU":"D",
"precooling":[
],
"subZone":[
]
},
{
"name":"AHU-C-Z1",
"AHU":"C",
"_id":{
"$oid":"5ac09c898249affa03506eff"
},
"precooling":[
],
"subZone":[
]
},
{
"name":"AHU-C-Z3",
"AHU":"C",
"_id":{
"$oid":"5ac09c898249affa03506efe"
},
"precooling":[
],
"subZone":[
]
}
],
"__v":2
}{
"_id":{
"$oid":"5aba46c41c8d5e4b52462aea"
},
"name":"123123",
"coordinate":[
12,
31
],
"yearlyEnergyCost":12321,
"zone":[
{
"name":"123423",
"_id":{
"$oid":"5aba46c41c8d5e4b52462aeb"
},
"precooling":[
],
"subZone":[
]
}
],
"__v":0
}
回答1:
You can use $redact
operator:
db.buildings.aggregate([
{$match:{"zone.AHU":{$exists:true}}},
{$redact:{
$cond:{
if:{$or:[{$eq:["$AHU","C"]},{$not: "$AHU"}]},
then:"$$DESCEND",
else:"$$PRUNE"
}
}}
])
Remember {$not: "$AHU"}
is important to be included so that top element will not be excluded. If not added, top element will be skipped and hence skipping the entire embedded document.
Output:
{
"_id" : ObjectId("5aba4460a042dc4a2fdf26cd"),
"name" : "Test Street",
"coordinate" : [
12,
31
],
"yearlyEnergyCost" : 1444,
"zone" : [
{
"name" : "AHU-C-Z2",
"_id" : ObjectId("5aba4460a042dc4a2fdf26ce"),
"AHU" : "C",
"precooling" : [],
"subZone" : []
},
{
"name" : "AHU-C-Z1",
"AHU" : "C",
"_id" : ObjectId("5ac09c898249affa03506eff"),
"precooling" : [],
"subZone" : []
},
{
"name" : "AHU-C-Z3",
"AHU" : "C",
"_id" : ObjectId("5ac09c898249affa03506efe"),
"precooling" : [],
"subZone" : []
}
],
"__v" : 2
}
来源:https://stackoverflow.com/questions/49611773/retrieve-multiple-queried-elements-in-an-object-array-in-mongodb-collection