查找包含特定值的数组的文档

如果我有这种图式。

person = {
name : String,
favoriteFoods : Array
}

... 其中favoriteFoods数组用字符串填充。我怎样用猫鼬找到所有喜欢吃“寿司”的人?

我希望你能说出这样的话:

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

(我知道mongodb中没有$contains,只是解释了我在知道解决方案之前期望找到的东西)

703405 次浏览

因为favouriteFoods是一个简单的字符串数组,你可以直接查询该字段:

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

但我也建议在你的schema中显式地使用string数组:

person = {
name : String,
favouriteFoods : [String]
}

相关文档可以在这里找到:https://docs.mongodb.com/manual/tutorial/query-arrays/

mongodb中没有$contains操作符。

你可以使用来自JohnnyHK的答案。与mongo的contains最接近的类比是$in,使用这个你的查询将看起来像:

PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);

我知道这个话题很老了,但对于未来可能会想知道同样问题的人来说,另一个非常低效的解决方案可能是:

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

这避免了MongoDB的所有优化,所以不要在生产代码中使用。

如果你需要在子文档数组中查找包含NULL元素的文档,我发现这个查询工作得很好:

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

这个查询来自这篇文章:MongoDb查询数组的空值

这是一个伟大的发现,它比我自己最初的和错误的版本要好得多(它只适用于只有一个元素的数组):

.find({
'MyArrayOfSubDocuments': { $not: { $size: 0 } },
'MyArrayOfSubDocuments._id': { $exists: false }
})

我觉得$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"});

对于Loopback3,所有给出的例子都不适合我,或者无论如何都不如使用REST API快。但它帮助我找到了我需要的确切答案。

# EYZ0

尽管同意find()在您的用例中是最有效的。仍然有$match的聚合框架,以简化大量条目的查询,并生成少量对您有价值的结果,特别是用于分组和创建新文件。

  PersonModel.aggregate([
{
"$match": {
$and : [{ 'favouriteFoods' : { $exists: true, $in: [ 'sushi']}}, ........ ]  }
},
{ $project : {"_id": 0, "name" : 1} }
]);

如果你想通过javascript使用“contains”操作符,你总是可以使用正则表达式…

< p >。 假设您希望检索名称为“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);
}

如果lookup_food_array是array。

match_stage["favoriteFoods"] = {'$elemMatch': {'$in': lookup_food_array}}

如果lookup_food_array是string。

match_stage["favoriteFoods"] = {'$elemMatch': lookup_food_string}

有一些方法可以实现这一点。第一个是通过$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。

我从我的项目中得到这些代码片段,我必须找到具有特定类别/类别的文档,所以你可以根据你的需要轻松地定制它。

填充 &在美元这段代码将是有用的。

ServiceCategory.find().populate({
path: "services",
match: { zipCodes: {$in: "10400"}},
populate: [
{
path: "offers",
},
],
});

如果你在一个对象数组中搜索,你可以使用$elemMatch。例如:

PersonModel.find({ favoriteFoods : { $elemMatch: { name: "sushiOrAnytthing" }}});