Le query standard non possono "confrontare" i valori nei documenti. Questo è in realtà qualcosa che fai usando .aggregate()
e $redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Qui utilizziamo $filter
per confrontare i valori di "amount"
nel documento padre a quelli all'interno dell'array. Se almeno uno è "uguale", allora "$$KEEP"
il documento, altrimenti "$$PRUNE"
Nelle versioni più recenti, possiamo abbreviarlo usando $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Se in realtà volevi anche solo gli "elementi corrispondenti dell'array", dovresti aggiungere un $filter
in proiezione:
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" ] }
}
}
}}
])
Ma il principio fondamentale è ovviamente quello di "ridurre" il numero di documenti restituiti a solo quelli che effettivamente soddisfano la condizione come priorità "prima". Altrimenti stai solo facendo calcoli inutili e lavori che richiedono tempo e risorse, per risultati che in seguito vorresti scartare.
Quindi prima "filtra" e poi "rimodella" come priorità.