如果我有这个架构......
person = {
name : String,
favoriteFoods : Array
}
...其中 favoriteFoods
数组填充了字符串。我怎样才能找到所有使用猫鼬将“寿司”作为他们最喜欢的食物的人?
我希望有一些类似的东西:
PersonModel.find({ favoriteFoods : { $contains : "sushi" }, function(...) {...});
(我知道mongodb中没有$contains
,只是解释一下我在知道解决方案之前期望找到的东西)
由于 favouriteFoods
是一个简单的字符串数组,您可以直接查询该字段:
PersonModel.find({ favouriteFoods: "sushi" }, ...); // favouriteFoods contains "sushi"
但我也建议在你的模式中明确地显示字符串数组:
person = {
name : String,
favouriteFoods : [String]
}
相关文档可在此处找到:https://docs.mongodb.com/manual/tutorial/query-arrays/
mongodb 中没有 $contains
运算符。
您可以使用 JohnnyHK 的答案。与包含 mongo 最接近的类比是 $in
,使用它您的查询将如下所示:
PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);
$in
。相反(这就是这个问题的目的),JohnnyHK 的回答是正确的。我本来打算投反对票,但我想这个答案可能对最终出现在此页面上的其他人有所帮助。
PersonModel.find({favouriteFoods: {"$in": ["sushi", "hotdog"]}})
我觉得 $all
在这种情况下会更合适。如果您正在寻找喜欢寿司的人,您可以:
PersonModel.find({ favoriteFood : { $all : ["sushi"] }, ...})
正如您可能想要过滤更多您的搜索,像这样:
PersonModel.find({ favoriteFood : { $all : ["sushi", "bananas"] }, ...})
$in
类似于 OR,$all
类似于 AND。检查这个:https://docs.mongodb.com/manual/reference/operator/query/all/
如果数组包含对象,例如 favouriteFoods
是以下对象的数组:
{
name: 'Sushi',
type: 'Japanese'
}
您可以使用以下查询:
PersonModel.find({"favouriteFoods.name": "Sushi"});
如果您需要在子文档数组中查找包含 NULL 元素的文档,我发现这个查询效果很好:
db.collection.find({"keyWithArray":{$elemMatch:{"$in":[null], "$exists":true}}})
此查询取自这篇文章:MongoDb query array with null values
这是一个很棒的发现,它比我自己的初始版本和错误版本好得多(结果证明它只适用于具有一个元素的数组):
.find({
'MyArrayOfSubDocuments': { $not: { $size: 0 } },
'MyArrayOfSubDocuments._id': { $exists: false }
})
lookup_food_array 的情况是数组。
match_stage["favoriteFoods"] = {'$elemMatch': {'$in': lookup_food_array}}
lookup_food_array 的情况是字符串。
match_stage["favoriteFoods"] = {'$elemMatch': lookup_food_string}
虽然同意 find() 在您的用例中最有效。仍然有 $match 聚合框架,以简化对大量条目的查询并生成对您有价值的少量结果,特别是对于分组和创建新文件。
PersonModel.aggregate([ { "$match": { $and : [{ 'favouriteFoods' : { $exists: true, $in: [ 'sushi']}}, ........ ] } }, { $project : {"_id": 0, "name" : 1} } ]);
有一些方法可以实现这一点。第一个是 $elemMatch
运算符:
const docs = await Documents.find({category: { $elemMatch: {$eq: 'yourCategory'} }});
// you may need to convert 'yourCategory' to ObjectId
第二个是由 $in
或 $all
运算符:
const docs = await Documents.find({category: { $in: [yourCategory] }});
或者
const docs = await Documents.find({category: { $all: [yourCategory] }});
// you can give more categories with these two approaches
//and again you may need to convert yourCategory to ObjectId
$in
类似于 OR,$all
类似于 AND。有关详细信息,请查看此链接:https://docs.mongodb.com/manual/reference/operator/query/all/
第三个是 aggregate()
函数:
const docs = await Documents.aggregate([
{ $unwind: '$category' },
{ $match: { 'category': mongoose.Types.ObjectId(yourCategory) } }
]};
使用 aggregate() 您只能在类别数组中获得一个类别 ID。
我从我的项目中获得了这些代码片段,我必须在其中找到具有特定类别/类别的文档,因此您可以根据需要轻松自定义它。
对于 Loopback3,给出的所有示例都对我不起作用,或者无论如何都与使用 REST API 一样快。但它帮助我找出了我需要的确切答案。
{"where":{"arrayAttribute":{ "all" :[String]}}}
使用 populate & $in 此代码将很有用。
ServiceCategory.find().populate({
path: "services",
match: { zipCodes: {$in: "10400"}},
populate: [
{
path: "offers",
},
],
});
如果您在对象数组中进行搜索,您可以使用 $elemMatch
。例如:
PersonModel.find({ favoriteFoods : { $elemMatch: { name: "sushi" }});
如果您想通过 javascript 使用诸如“包含”运算符之类的东西,您可以随时使用正则表达式...
例如。假设您要检索名称为“Bartolomew”的客户
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);
}
我知道这个话题很老了,但对于未来可能想知道同样问题的人来说,另一个非常低效的解决方案可能是:
PersonModel.find({$where : 'this.favouriteFoods.indexOf("sushi") != -1'});
这避免了 MongoDB 的所有优化,因此不要在生产代码中使用。
favouriteFoods
为:favouriteFoods:[{type:Schema.Types.ObjectId, ref:'Food'}]
,这也适用PersonModel.find({ favouriteFoods.text: "sushi" }, ...); person = { name : String, favouriteFoods : [{text:String}] }
db.person.find( { favouriteFoods: { $all: ["sushi", "sashimi"] } } )
将返回所有喜欢“寿司”和“生鱼片”的人,有人在下面指出了一些答案