Las consultas estándar no pueden "comparar" valores en documentos. En realidad, esto es algo que haces usando .aggregate()
y $redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Aquí usamos $filter
para comparar los valores de "amount"
en el documento padre a aquellos dentro de la matriz. Si al menos uno es "igual", entonces "$$KEEP"
el documento, de lo contrario "$$PRUNE"
En las versiones más recientes, podemos acortarlo usando $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Si en realidad solo quisiera los "elementos de matriz coincidentes", entonces agregaría un $filter
en proyección:
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" ] }
}
}
}}
])
Pero el principio fundamental es, por supuesto, "reducir" el número de documentos devueltos a solo aquellos que realmente cumplen la condición como una "primera" prioridad. De lo contrario, solo está haciendo cálculos y trabajos innecesarios que consumen tiempo y recursos, para obtener resultados que luego descartaría.
Así que "filtrar" primero y "remodelar" segundo como prioridad.