Zapytania standardowe nie mogą „porównywać” wartości w dokumentach. W rzeczywistości jest to coś, co robisz za pomocą .aggregate()
i $redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Tutaj używamy $filter
aby porównać wartości "amount"
w dokumencie nadrzędnym do tych w tablicy. Jeśli przynajmniej jeden jest "równy", to "$$KEEP"
dokument, w przeciwnym razie "$$PRUNE"
W najnowszych wersjach możemy to skrócić, używając $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Jeśli faktycznie chcesz tylko „pasujące elementy tablicy”, dodaj $filter
w projekcji:
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 główną zasadą jest oczywiście „zmniejszenie” liczby zwracanych dokumentów do tylko te, które faktycznie spełniają warunek jako „pierwszy” priorytet. W przeciwnym razie po prostu wykonujesz niepotrzebne obliczenia i pracę, która wymaga czasu i zasobów, aby uzyskać wyniki, które później odrzucisz.
Zatem najpierw „przefiltruj”, a jako priorytet „przekształć”.