Standardforespørgsler kan ikke "sammenligne" værdier i dokumenter. Dette er faktisk noget, du gør ved at bruge .aggregate()
og $redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Her bruger vi $filter
for at sammenligne værdierne for "amount"
i det overordnede dokument til dem i arrayet. Hvis mindst én er "lig", så "$$KEEP"
dokumentet, ellers "$$PRUNE"
I de seneste versioner kan vi forkorte det ved at bruge $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Hvis du faktisk også kun ville have "matchende array-element(er)", så ville du tilføje 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 hovedprincippet er naturligvis at "reducere" antallet af dokumenter, der returneres til kun dem, der faktisk matcher betingelsen som en "første" prioritet. Ellers laver du bare unødvendige beregninger og arbejde, der tager tid og ressourcer, for resultater, som du senere ville kassere.
Så "filtrer" først, og "omform" derefter som en prioritet.