Найти документ с массивом, который содержит определенное значение

264

Если у меня есть эта схема...

person = {
    name : String,
    favoriteFoods : Array
}

... где массив favoriteFoods заполняется строками. Как я могу найти всех людей, которые имеют "суши" как свою любимую пищу с помощью мангуста?

Я надеялся на что-то вроде:

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

(Я знаю, что в mongodb нет $contains, просто объясняя, что я ожидал найти, прежде чем знать решение)

Теги:
mongoose

6 ответов

372
Лучший ответ

Поскольку favouriteFoods - это простой массив строк, вы можете просто запросить это поле напрямую:

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

Но я также рекомендую сделать строковый массив явным в вашей схеме:

person = {
    name : String,
    favouriteFoods : [String]
}
  • 46
    Кстати, вот документация: docs.mongodb.org/manual/tutorial/query-documents/…
  • 10
    Это также работает , если favouriteFoods является: favouriteFoods:[{type:Schema.Types.ObjectId, ref:'Food'}]
Показать ещё 3 комментария
88

В mongodb нет оператора $contains.

Вы можете использовать ответ JohnnyHK, который работает. Ближайшая аналогия с тем, что mongo имеет $in, используя этот запрос, будет выглядеть так:

PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);
  • 9
    Это правильно? Разве mongodb не ожидает массив значений при использовании $ in? как {имя: {$ in: ["Пол", "Дейв", "Ларри", "Адам"]}}?
  • 0
    Извините, вы правы, я соответственно обновил код
Показать ещё 7 комментариев
21

Если вам нужно найти документы, содержащие элементы NULL внутри массива поддокументов, я нашел этот запрос, который работает очень хорошо:

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

Этот запрос взят из этого сообщения: массив запросов MongoDb с нулевыми значениями

Это была отличная находка, и она работает намного лучше, чем моя первоначальная и неправильная версия (которая, как оказалось, отлично работает только для массивов с одним элементом):

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

Мне кажется, что $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/

  • 0
    Извините, это неправильный ответ на мой вопрос. Я не ищу точное соответствие, а только для массивов, которые содержат по крайней мере указанное значение.
  • 12
    Это совершенно правильный ответ на ваш вопрос! Для одного значения нет разницы в использовании $ all или $ in. Если у вас есть несколько значений, таких как "суши", "бананы", $ all ищет людей, у которых есть "суши" И "бананы" в их массиве favourFood, если при использовании $ вы получаете людей, у которых есть "суши" ИЛИ "бананы" "в их любимом массиве еды.
Показать ещё 2 комментария
9

Если массив содержит объекты, например, если favouriteFoods - это массив объектов следующего типа:

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

вы можете использовать следующий запрос:

PersonModel.find({"favouriteFoods.name": "Sushi"});
  • 0
    Это легко лучший ответ. Намного легче использовать, когда вы спешите.
-15

Я знаю, что эта тема старая, но для будущих людей, которые могут задаться вопросом по тому же вопросу, можно было бы сделать еще одно невероятно неэффективное решение:

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

Это позволяет избежать всех оптимизаций MongoDB, поэтому не используйте в производственном коде.

  • 0
    Из любопытства, есть ли преимущество в том, чтобы делать это таким образом?
  • 43
    На самом деле это супер неэффективно ...
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню