616

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

person = {
    name : String,
    favoriteFoods : Array
}

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

我希望有一些类似的东西:

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

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

4

12 回答 12

852

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

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

但我也建议在你的模式中明确地显示字符串数组:

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

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

于 2013-08-09T14:18:58.543 回答
191

mongodb中没有$contains运算符。

您可以使用 JohnnyHK 的答案。与包含 mongo 最接近的类比是$in,使用它,您的查询将如下所示:

PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);
于 2013-08-09T14:30:51.377 回答
129

我觉得$all在这种情况下会更合适。如果您正在寻找喜欢寿司的人,您可以:

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

正如您可能想要过滤更多您的搜索,像这样:

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

$in就像 OR 和$allAND 一样。检查这个:https ://docs.mongodb.com/manual/reference/operator/query/all/

于 2017-01-19T15:31:29.223 回答
101

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

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

您可以使用以下查询:

PersonModel.find({"favouriteFoods.name": "Sushi"});
于 2017-08-08T10:37:32.423 回答
34

如果您需要在子文档数组中查找包含 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 }
})
于 2015-09-08T10:29:12.430 回答
9

lookup_food_array 的情况是数组。

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

lookup_food_array 的情况是字符串。

match_stage["favoriteFoods"] = {'$elemMatch': lookup_food_string}
于 2019-05-02T15:56:22.217 回答
3

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

  PersonModel.aggregate([
            { 
                 "$match": { 
                     $and : [{ 'favouriteFoods' : { $exists: true, $in: [ 'sushi']}}, ........ ]  }
             },
             { $project : {"_id": 0, "name" : 1} }
            ]);
于 2018-07-18T06:18:39.487 回答
1

使用populate & $in此代码将很有用。

ServiceCategory.find().populate({
    path: "services",
    match: { zipCodes: {$in: "10400"}},
    populate: [
        {
            path: "offers",
        },
    ],
});
于 2021-08-14T11:31:34.317 回答
1

对于 Loopback3,给出的所有示例都对我不起作用,或者无论如何都与使用 REST API 一样快。但它帮助我找出了我需要的确切答案。

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

于 2018-03-26T03:31:57.867 回答
0

有一些方法可以实现这一点。第一个是按$elemMatch操作员:

const docs = await Documents.find({category: { $elemMatch: {$eq: 'yourCategory'} }});
// you may need to convert 'yourCategory' to ObjectId

第二个是由$inor$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 和$allAND 一样。有关更多详细信息,请查看此链接: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。

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

于 2021-07-25T06:18:09.173 回答
-5

如果您想通过 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);
}
于 2018-09-06T21:58:35.887 回答
-25

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

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

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

于 2014-05-06T19:32:11.277 回答