Standaardquery's kunnen geen waarden in documenten "vergelijken". Dit is eigenlijk iets wat je doet met .aggregate()
en $redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Hier gebruiken we $filter
om de waarden van "amount"
te vergelijken in het bovenliggende document naar die binnen de array. Als ten minste één "gelijk" is, dan "$$KEEP"
het document, anders "$$PRUNE"
In de meest recente versies kunnen we dat inkorten met $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Als je eigenlijk alleen de "overeenkomstige array-element(en)" ook wilt, dan zou je een $filter
in projectie:
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" ] }
}
}
}}
])
Maar het belangrijkste principe is natuurlijk om het aantal teruggestuurde documenten te "verminderen" tot alleen degenen die daadwerkelijk overeenkomen met de voorwaarde als een "eerste" prioriteit. Anders doe je gewoon onnodige berekeningen en werk dat tijd en middelen kost, voor resultaten die je later zou weggooien.
Dus "filter" eerst en "hervorm" als prioriteit.