Standardní dotazy nemohou "porovnávat" hodnoty v dokumentech. To je ve skutečnosti něco, co děláte pomocí .aggregate()
a $redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Zde používáme $filter
pro porovnání hodnot "amount"
v nadřazeném dokumentu k těm v poli. Pokud je alespoň jeden "rovný", pak "$$KEEP"
dokument, jinak "$$PRUNE"
V nejnovějších verzích to můžeme zkrátit pomocí $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Pokud byste ve skutečnosti chtěli také pouze „odpovídající element(y) pole“, pak byste přidali $filter
v projekci:
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" ] }
}
}
}}
])
Ale hlavní zásadou je samozřejmě „snížit“ počet vracených dokumentů na pouze ty, které skutečně odpovídají podmínce jako „první“ priorita. Jinak jen děláte zbytečné výpočty a práci, která zabírá čas a zdroje, abyste získali výsledky, které byste později zahodili.
Nejprve tedy „filtrujte“ a poté „přetvářejte“ jako prioritu.