Buscar documento con matriz que contiene un valor específico


Si tengo este esquema...

person = {
    name : String,
    favoriteFoods : Array
}

... donde la matriz favoriteFoods se rellena con cadenas. ¿Cómo puedo encontrar a todas las personas que tienen "sushi" como su comida favorita usando mangosta?

Esperaba algo parecido a:

PersonModel.find({ favoriteFoods : { $contains : "sushi" }, function(...) {...});

(Sé que no hay $contains en mongodb, solo explicando lo que esperaba encontrar antes de conocer la solución)

Author: ᴀʀᴍᴀɴ, 2013-08-09

9 answers

Como favouriteFoods es una simple matriz de cadenas, puede consultar ese campo directamente:

PersonModel.find({ favouriteFoods: "sushi" }, ...);

Pero también recomendaría hacer explícita la matriz de cadenas en su esquema:

person = {
    name : String,
    favouriteFoods : [String]
}
 495
Author: JohnnyHK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-13 16:36:12

No hay un operador $contains en mongodb.

Puedes usar la respuesta de JohnnyHK ya que funciona. La analogía más cercana a contiene que tiene mongo es $in, usando esto su consulta se vería como:

PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);
 104
Author: Alistair Nelson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-09 14:46:14

Creo que $all sería más apropiado en esta situación. Si usted está buscando a la persona que está en el sushi que hacer :

PersonModel.find({ favoriteFood : { $all : ["sushi"] }, ...})

Como es posible que desee filtrar más su búsqueda, así :

PersonModel.find({ favoriteFood : { $all : ["sushi", "bananas"] }, ...})

$in es como O y $all gusta Y. Compruebe esto: https://docs.mongodb.com/manual/reference/operator/query/all /

 45
Author: Pobe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-19 15:31:29

En caso de que necesite encontrar documentos que contengan elementos NULOS dentro de una matriz de sub-documentos, he encontrado esta consulta que funciona bastante bien:

db.collection.find({"keyWithArray":{$elemMatch:{"$in":[null], "$exists":true}}})

Esta consulta se toma de este post: Matriz de consulta MongoDB con valores nulos

Fue un gran hallazgo y funciona mucho mejor que mi propia versión inicial y incorrecta (que resultó funcionar bien solo para matrices con un elemento):

.find({
    'MyArrayOfSubDocuments': { $not: { $size: 0 } },
    'MyArrayOfSubDocuments._id': { $exists: false }
})
 27
Author: Jesus Campon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:19

En caso de que el array contenga objetos, por ejemplo, si favouriteFoods es un array de objetos de los siguientes:

{
  name: 'Sushi',
  type: 'Japanese'
}

Puede utilizar la siguiente consulta:

PersonModel.find({"favouriteFoods.name": "Sushi"});
 21
Author: Kfir Erez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-08 10:37:32

Para Loopback3 todos los ejemplos dados no funcionaron para mí, o tan rápido como usar la API REST de todos modos. Pero me ayudó a encontrar la respuesta exacta que necesitaba.

{"where":{"arrayAttribute":{ "all" :[String]}}}

 1
Author: Mark Ryan Orosa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 02:43:31

Aunque estar de acuerdo con find() es más efectivo en tu caso de uso. Todavía hay match match of aggregation framework, para facilitar la consulta de un gran número de entradas y generar un bajo número de resultados que tienen valor para usted especialmente para agrupar y crear nuevos archivos.

  PersonModel.aggregate([
            { 
                 "$match": { 
                     $and : [{ 'favouriteFoods' : { $exists: true, $in: [ 'sushi']}}, ........ ]  }
             },
             { $project : {"_id": 0, "name" : 1} }
            ]);
 0
Author: FullStack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-18 06:18:39

Si desea usar algo como un operador "contains" a través de javascript, siempre puede usar una expresión regular para eso...

Eg. Supongamos que desea recuperar un cliente con "Bartolomew" como nombre

async function getBartolomew() {
    const custStartWith_Bart = await Customers.find({name: /^Bart/ }); // Starts with Bart
    const custEndWith_lomew = await Customers.find({name: /lomew$/ }); // Ends with lomew
    const custContains_rtol = await Customers.find({name: /.*rtol.*/ }); // Contains rtol

    console.log(custStartWith_Bart);
    console.log(custEndWith_lomew);
    console.log(custContains_rtol);
}
 0
Author: Alingenomen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-06 21:58:35

Sé que este tema es viejo, pero para las personas futuras que podrían preguntarse la misma pregunta, otra solución increíblemente ineficiente podría ser hacer:

PersonModel.find({$where : 'this.favouriteFoods.indexOf("sushi") != -1'});

Esto evita todas las optimizaciones de MongoDB, por lo que no utilice código de producción.

 -20
Author: user3027146,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-24 15:58:15