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)
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]
}
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"]} }, ...);
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 /
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 }
})
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"});
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]}}}
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} } ]);
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);
}
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.