Solución:
Como se dijo, $where
es una buena opción en la que no es necesario continuar con la lógica en la canalización de agregación.
Pero si lo hace, use $redact
, con $map
para transformar el “valor” en una matriz y el uso de $setIsSubSet
comparar. Es la forma más rápida de hacer esto, ya que no necesita duplicar documentos usando $unwind
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": { "$setIsSubset": [
{ "$map": {
"input": { "$literal": ["A"] },
"as": "a",
"in": "$value"
}},
"$array"
]},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
El $redact
El operador de tubería permite el procesamiento de una condición lógica dentro de $cond
y utiliza las operaciones especiales $$KEEP
para “mantener” el documento donde la condición lógica es verdadera o $$PRUNE
para “eliminar” el documento donde la condición era falsa.
Esto le permite funcionar como $project
con una subsecuente $match
, pero en una sola etapa de pipeline que es más eficiente.
Teniendo en cuenta que se trata de operadores codificados nativos y no de JavaScript, es probable que sea “la” forma más rápida de realizar su coincidencia. Entonces, siempre que esté utilizando una versión de MongoDB 2.6 o superior, esta es la forma en que debe hacerlo para comparar estos elementos en su documento.
Puede utilizar la expresión de agregación en una consulta regular en la versión 3.6.
db.collection_name.find({"$expr": {"$in": ["$value", "$array"]}})
Usando agregación:
Puedes usar $match + $expr
en corriente 3.6
versión.
db.collection_name.aggregate({"$match": {"$expr": {"$in": ["$value", "$array"]}}})
Puedes probar $redact + $in
expresión en 3.4
versión.
db.collection_name.aggregate({
"$redact": {
"$cond": [
{
"$in": [
"$value",
"$array"
]
},
"$$KEEP",
"$$PRUNE"
]
}
})
Una ligera variación basada en la respuesta de @ chridam:
db.test.aggregate([
{ "$unwind": "$array" },
{ "$group": {
_id: { "_id": "$_id", "value": "$value" },
array: { $push: "$array" },
mcount: { $sum: {$cond: [{$eq: ["$value","$array"]},1,0]}}
}
},
{ $match: {mcount: {$gt: 0}}},
{ "$project": { "value": "$_id.value", "array": 1, "_id": 0 }}
])
La idea es $unwind
y $group
retrocede la matriz, contando en mcount
el número de elementos que coinciden con el valor. Después de eso, un simple $match
en mcount > 0
filtrará los documentos no deseados.