Стандартните заявки не могат да "сравняват" стойности в документи. Това всъщност е нещо, което правите с помощта на .aggregate()
и $redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Тук използваме $filter
за да сравните стойностите на "amount"
в родителския документ към тези в масива. Ако поне едно е „равно“, тогава ние "$$KEEP"
документа, в противен случай ние "$$PRUNE"
В най-новите версии можем да го съкратим с помощта на $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Ако всъщност искате само „елемент(и) на съвпадащ масив“, тогава бихте добавили $filter
в проекция:
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" ] }
}
}
}}
])
Но основният принцип, разбира се, е да се „намали“ броят на върнатите документи до само тези, които действително отговарят на условието като "първи" приоритет. В противен случай вие просто правите ненужни изчисления и работа, която отнема време и ресурси, за резултати, които по-късно бихте отхвърлили.
Така че първо „филтрирайте“ и второ „преоформете“ като приоритет.