Standardfrågor kan inte "jämföra" värden i dokument. Detta är faktiskt något du gör med .aggregate()
och $redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Här använder vi $filter
för att jämföra värdena för "amount"
i det överordnade dokumentet till de inom arrayen. Om minst en är "lika" så "$$KEEP"
dokumentet, annars "$$PRUNE"
I de senaste versionerna kan vi förkorta det med $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Om du faktiskt bara ville ha "matchande arrayelement" också, då skulle du lägga till en $filter
i projektion:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"amount": 1,
"offers": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}
}}
])
Men huvudprincipen är förstås att "minska" antalet dokument som returneras till endast de som faktiskt matchar villkoret som en "första" prioritet. Annars gör du bara onödiga beräkningar och arbete som tar tid och resurser, för resultat som du senare skulle förkasta.
Så "filtrera" först och "omforma" sedan som en prioritet.