Запрос массива MongoDB — выделить элемент массива

#arrays #mongodb

#массивы #mongodb

Вопрос:

У меня возникли проблемы с запросом коллекции MongoDB с массивом внутри.
Вот структура моей коллекции, которую я запрашиваю. Это одна запись:

 {
"_id": "abc123def4567890",
"profile_id": "abc123def4567890",
"image_count": 2,
"images": [
  {
    "image_id": "ABC123456789",
    "image_url": "images/something.jpg",
    "geo_loc": "-0.1234,11.234567890",
    "title": "A Title",
    "shot_time": "01:23:33",
    "shot_date": "11/22/2222",
    "shot_type": "scenery",
    "conditions": "cloudy",
    "iso": 16,
    "f": 2.4,
    "ss": "1/545",
    "focal": 6.0,
    "equipment": "",
    "instructions": "",
    "upload_date": 1234567890,
    "update_date": 1234567890
  },
  {
    "image_id": "ABC123456789",
    "image_url": "images/something.jpg",
    "geo_loc": "-0.1234,11.234567890",
    "title": "A Title",
    "shot_time": "01:23:33",
    "shot_date": "11/22/2222",
    "shot_type": "portrait",
    "conditions": "cloudy",
    "iso": "16",
    "f": "2.4",
    "ss": "1/545",
    "focal": "6.0",
    "equipment": "",
    "instructions": "",
    "upload_date": 1234567890,
    "update_date": 1234567890
  }
]
}
 

Простите за форматирование, я не знал, как еще это показать.

Как вы можете видеть, это профиль с серией изображений в массиве под названием «изображения», и в нем есть 2 изображения. Каждый из элементов массива «изображения» содержит объект атрибутов для изображения (URL, заголовок, тип и т.д.).

Все, что я хочу сделать, это вернуть элемент object, атрибуты которого соответствуют определенным критериям:

Выберите объект из изображений, который имеет shot_type = «scenery»

Я попытался сделать это как можно проще, поэтому начал с:

 find( { "images.shot_type": "scenery" } )
 

Это возвращает всю запись и оба изображения внутри. Итак, я попробовал проекцию, но не смог выделить отдельный объект в массиве (в данном случае объект в позиции 0) и вернуть его.

Я думаю, что ответ лежит в проекции, но я не уверен.

Я уже несколько часов просматриваю документы MongoDB и не могу найти вдохновения. Я прочитал о $ elemMatch, $ и других операторах массива, похоже, ничто не позволяет вам выделить элемент массива на основе данных внутри. Я тоже просматривал эту страницу https://docs.mongodb.com/manual/tutorial/query-arrays / Все еще не могу разобраться в этом.

  1. Кто-нибудь может оказать помощь?
  2. Допустил ли я ошибку, используя ‘$ push’ для заполнения моего поля изображений (превращая его в массив) вместо использования ‘$ set’, который превратил бы его во встроенный документ? Имело бы это значение?

Ответ №1:

Использование агрегации:

 db.collection.aggregate({
  $project: {
    _id: 0,
    "result": {
      $filter: {
        input: "$images",
        as: "img",
        cond: {
          $eq: [
            "$img.shot_type",
            "scenery"
          ]
        }
      }
    }
  }
})
 

Игровая площадка

Комментарии:

1. Спасибо вам за это. Мне нужно больше узнать об агрегации. Я думал, что смогу выполнить этот запрос с помощью простого «find». Я был неправ.

2. Пожалуйста. Есть бесплатные курсы по mongo db. Возьмите хотя бы один из этих @Phfog. Занимает 1 или 2 дня. Научитесь использовать $match и $project и $unwind этого почти достаточно

Ответ №2:

Вы можете использовать $elemMatch таким образом (упрощенный запрос):

 db.collection.find({
  "profile_id": "1",
},
{
  "images": {
    "$elemMatch": {
      "shot_type": 1
    }
  }
})
 

Вы можете использовать два объекта в find запросе. Первый отфильтрует весь документ и получит только те, значение которых profile_id равно 1. Вы можете пропустить этот этап и использовать только { } в том случае, если вы хотите выполнить поиск по всей коллекции.
Затем другой объект использует $elemMatch для получения только элемента, значение которого shot_type равно 1.

Проверьте пример здесь