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

时间:2013-08-09 13:46:14

标签: mongodb mongoose

如果我有这个架构......

person = {
    name : String,
    favoriteFoods : Array
}

... favoriteFoods数组填充了字符串。我怎样才能找到所有使用猫鼬“寿司”作为他们最喜欢的食物的人?

我希望有类似的内容:

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

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

11 个答案:

答案 0 :(得分:581)

由于favouriteFoods是一个简单的字符串数组,您可以直接查询该字段:

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

但我还建议在你的架构中明确地使用字符串数组:

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

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

答案 1 :(得分:125)

mongodb中没有$contains运算符。

你可以使用JohnnyHK的答案。与mongo包含的最接近的类比是$in,使用此查询看起来像:

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

答案 2 :(得分:66)

在这种情况下,我觉得 [HttpPost] public virtual ActionResult SearchSpecificNutritionalPurpose(SpecificNutritionalPurposeSearchViewModel searchParameters) { var searchResult = _dictionaryRepository.FindSpecificNutritionalPurpose(searchParameters.EANCode, searchParameters.Name, searchParameters.InternationalName).Take(100).ToList(); return PartialView("Modals/_SpecificNutritionalPurposeSearchResult", searchResult); } 会更合适。如果您正在寻找寿司的人,请:

$all

您可能希望过滤更多搜索,例如:

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

PersonModel.find({ favoriteFood : { $all : ["sushi", "bananas"] }, ...}) 就像OR一样,$in就像AND一样。检查一下:https://docs.mongodb.com/manual/reference/operator/query/all/

答案 3 :(得分:37)

如果数组包含对象,例如favouriteFoods是以下对象的数组:

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

您可以使用以下查询:

PersonModel.find({"favouriteFoods.name": "Sushi"});

答案 4 :(得分:30)

如果你需要在子文档数组中找到包含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 }
})

答案 5 :(得分:2)

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

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

答案 6 :(得分:1)

对于Loopback3,给出的所有示例对我来说都不起作用,或者与使用REST API一样快。但它帮助我弄清楚我需要的确切答案。

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

答案 7 :(得分:0)

如果lookup_food_array是数组。

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

如果lookup_food_array是字符串。

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

答案 8 :(得分:0)

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

我从我的项目中获得了这些代码片段,我必须在其中找到具有特定类别/类别的文档,因此您可以根据需要轻松自定义它。

答案 9 :(得分:-1)

如果您想通过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);
}

答案 10 :(得分:-24)

我知道这个话题已经过时了,但是对于那些可能会怀疑同样问题的未来人来说,另一个非常低效的解决方案可能就是:

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

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