Trouver un document avec un tableau qui contient une valeur spécifique

Si j'ai ce schéma...

person = {
    name : String,
    favoriteFoods : Array
}

... où le tableau favoriteFoods est peuplé de chaînes. Comment puis-je trouver toutes les personnes qui ont "sushi" comme nourriture préférée en utilisant la mangouste?

j'espérais quelque chose du genre:

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

(je sais qu'il n'y a pas de $contains en mongodb, expliquant simplement ce que je m'attendais à trouver avant de connaître la solution)

332
demandé sur ᴀʀᴍᴀɴ 2013-08-09 17:46:14

9 réponses

comme favouriteFoods est un tableau simple de chaînes, vous pouvez simplement interroger ce champ directement:

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

mais je recommande aussi de rendre le tableau string explicite dans votre schéma:

person = {
    name : String,
    favouriteFoods : [String]
}
495
répondu JohnnyHK 2015-12-13 16:36:12

il n'y a pas d'opérateur $contains à mongodb.

vous pouvez utiliser la réponse de JohnnyHK comme cela fonctionne. L'analogie la plus proche de contient que mongo A est $in , en utilisant cela votre requête ressemblerait à:

PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);
104
répondu Alistair Nelson 2013-08-09 14:46:14

j'ai l'impression que $all serait plus approprié dans cette situation. Si vous cherchez quelqu'un qui aime les sushis vous faites:

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

comme vous pourriez vouloir filtrer plus votre recherche, comme ainsi:

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

$in , c'est comme OU et $all comme ET. Vérifiez ceci: https://docs.mongodb.com/manual/reference/operator/query/all /

45
répondu Pobe 2017-01-19 15:31:29

dans le cas où vous devez trouver des documents qui contiennent des éléments NULS à l'intérieur d'un tableau de sous-documents, j'ai trouvé cette requête qui fonctionne assez bien:

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

cette requête est tirée de ce post: MongoDb tableau de requête avec des valeurs nulles

il était une grande trouvaille et il fonctionne beaucoup mieux que mon propre initiale et faux "1519100920 version" (qui s'est avéré fonctionner très bien que pour les tableaux avec un élément):

.find({
    'MyArrayOfSubDocuments': { $not: { $size: 0 } },
    'MyArrayOfSubDocuments._id': { $exists: false }
})
27
répondu Jesus Campon 2017-05-23 11:55:19

dans le cas où le tableau contient des objets par exemple si favouriteFoods est un tableau d'objets de ce qui suit:

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

vous pouvez utiliser la requête suivante:

PersonModel.find({"favouriteFoods.name": "Sushi"});
21
répondu Kfir Erez 2017-08-08 10:37:32

pour Loopback3 tous les exemples donnés ne fonctionnaient pas pour moi, ou aussi vite que L'utilisation de L'API REST de toute façon. Mais il m'a aidé à trouver la réponse exacte dont j'avais besoin.

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

1
répondu Mark Ryan Orosa 2018-05-24 02:43:31

bien que d'accord avec find() est le plus efficace dans votre usecase. Il y a toujours $match of aggregation framework, pour faciliter la requête d'un grand nombre d'entrées et générer un petit nombre de résultats qui ont de la valeur pour vous, particulièrement pour le regroupement et la création de nouveaux fichiers.

  PersonModel.aggregate([
            { 
                 "$match": { 
                     $and : [{ 'favouriteFoods' : { $exists: true, $in: [ 'sushi']}}, ........ ]  }
             },
             { $project : {"_id": 0, "name" : 1} }
            ]);
0
répondu FullStack 2018-07-18 06:18:39

si vous voulez utiliser quelque chose comme un opérateur" contains " par javascript, vous pouvez toujours utiliser une expression régulière pour cela...

par exemple. Dites que vous voulez récupérer un client ayant "Barthélemy" comme nom

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
répondu Alingenomen 2018-09-06 21:58:35

je sais que ce sujet est vieux, mais pour les futurs gens qui pourraient se poser la même question, une autre solution incroyablement inefficace pourrait être de faire:

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

cela évite toutes les optimisations par MongoDB donc ne pas utiliser dans le code de production.

-20
répondu user3027146 2015-08-24 15:58:15