Найти документ с массивом, который содержит определенное значение
Если у меня есть эта схема...
person = {
name : String,
favoriteFoods : Array
}
... где массив favoriteFoods
заполняется строками. Как я могу найти всех людей, которые имеют "суши" как свою любимую пищу с помощью мангуста?
Я надеялся на что-то вроде:
PersonModel.find({ favoriteFoods : { $contains : "sushi" }, function(...) {...});
(Я знаю, что в mongodb нет $contains
, просто объясняя, что я ожидал найти, прежде чем знать решение)
Ответы
Ответ 1
Поскольку favouriteFoods
- это простой массив строк, вы можете просто запросить это поле напрямую:
PersonModel.find({ favouriteFoods: "sushi" }, ...);
Но я бы также рекомендовал сделать строковый массив явным в вашей схеме:
person = {
name : String,
favouriteFoods : [String]
}
Соответствующую документацию можно найти здесь: https://docs.mongodb.com/manual/tutorial/query-arrays/
Ответ 2
В mongodb нет оператора $contains
.
Вы можете использовать ответ JohnnyHK, который работает. Ближайшая аналогия с тем, что mongo имеет $in
, используя этот запрос, будет выглядеть так:
PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);
Ответ 3
Мне кажется, что $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/
Ответ 4
Если массив содержит объекты, например, если favouriteFoods
- это массив объектов следующего типа:
{
name: 'Sushi',
type: 'Japanese'
}
вы можете использовать следующий запрос:
PersonModel.find({"favouriteFoods.name": "Sushi"});
Ответ 5
Если вам нужно найти документы, содержащие элементы NULL внутри массива поддокументов, я нашел этот запрос, который работает очень хорошо:
db.collection.find({"keyWithArray":{$elemMatch:{"$in":[null], "$exists":true}}})
Этот запрос взят из этого сообщения: массив запросов MongoDb с нулевыми значениями
Это была отличная находка, и она работает намного лучше, чем моя первоначальная и неправильная версия (которая, как оказалось, отлично работает только для массивов с одним элементом):
.find({
'MyArrayOfSubDocuments': { $not: { $size: 0 } },
'MyArrayOfSubDocuments._id': { $exists: false }
})
Ответ 6
Хотя согласитесь с find() наиболее эффективным в вашем случае использования. Тем не менее, существует $ match структуры агрегации, чтобы упростить запрос большого количества записей и генерировать небольшое количество результатов, которые имеют ценность для вас, особенно для группировки и создания новых файлов.
PersonModel.aggregate([
{
"$match": {
$and : [{ 'favouriteFoods' : { $exists: true, $in: [ 'sushi']}}, ........ ] }
},
{ $project : {"_id": 0, "name" : 1} }
]);
Ответ 7
Для Loopback3 все приведенные примеры не помогли мне или так же быстро, как использование REST API. Но это помогло мне понять, какой именно ответ мне нужен.
{"where":{"arrayAttribute":{ "all" :[String]}}}
Ответ 8
Incase of lookup_food_array это массив.
match_stage["favoriteFoods"] = {'$elemMatch': {'$in': lookup_food_array}}
Incase of lookup_food_array это строка.
match_stage["favoriteFoods"] = {'$elemMatch': lookup_food_string}
Ответ 9
Если вы хотите использовать что-то вроде оператора "Содержит" через JavaScript, вы всегда можете использовать Регулярное выражение для этого...
например. Скажем, вы хотите получить клиента, который имеет имя "Бартоломью"
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
Я знаю, что эта тема старая, но для будущих людей, которые могут задаться вопросом по тому же вопросу, можно было бы сделать еще одно невероятно неэффективное решение:
PersonModel.find({$where : 'this.favouriteFoods.indexOf("sushi") != -1'});
Это позволяет избежать всех оптимизаций MongoDB, поэтому не используйте в производственном коде.