MongoDB: запрашивать и извлекать объекты внутри встроенного массива? - программирование
Подтвердить что ты не робот

MongoDB: запрашивать и извлекать объекты внутри встроенного массива?

Скажем, у меня есть следующая схема документа в коллекции под названием "пользователи":

{
    name: 'John',
    items: [ {}, {}, {}, ... ]
}

Массив элементов содержит объекты в следующем формате:

{
    item_id: "1234",
    name: "some item"
}

Каждый пользователь может иметь несколько элементов, встроенных в массив "items".

Теперь я хочу, чтобы иметь возможность извлекать элемент item_id для данного пользователя.

Например, я хочу получить элемент с идентификатором "1234", принадлежащим пользователю с именем "Джон".

Могу ли я сделать это с помощью mongoDB? Я бы хотел использовать его мощную индексацию массива, но я не уверен, что вы можете запускать запросы на встроенных массивах и возвращать объекты из массива вместо документа, который содержит его.

Я знаю, что могу получить пользователей, которые имеют определенный элемент, используя {users.items.item_id: "1234" }. Но я хочу получить фактический элемент из массива, а не пользователя.

Альтернативно, может быть, лучший способ организовать эти данные, чтобы я мог легко получить то, что хочу? Я до сих пор довольно новичок в mongodb.

Спасибо за любую помощь или совет, которые вы можете предоставить.

4b9b3361

Ответ 1

Вопрос старый, но с течением времени ответ изменился. С MongoDB >= 2.2 вы можете сделать:

db.users.find( { name: "John"}, { items: { $elemMatch: { item_id: "1234" } } })

У вас будет:

{
   name: "John",
   items: 
   [ 
       {
         item_id: "1234",
         name: "some item"
       }
   ]
}

См. документацию по $elemMatch

Ответ 2

Есть несколько вещей, чтобы отметить об этом:

1) Я считаю, что для людей, изучающих MongoDB, самое сложное - это UN-обучение реляционному мышлению, к которому они привыкли. Ваша модель данных выглядит правильно.

2) Обычно, что вы делаете с MongoDB, возвращаете весь документ в клиентскую программу, а затем ищите часть документа, который вы хотите на стороне клиента, используя свой язык программирования клиента.

В вашем примере вы получите весь "пользовательский" документ, а затем итерацию через массив "items []" на стороне клиента.

3) Если вы хотите вернуть только массив 'items []', вы можете сделать это, используя синтаксис "Выбор поля". Подробнее см. http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection. К сожалению, он вернет весь массив items [], а не только один элемент массива.

4) Для добавления этой функции существует существующий билет Jira: https://jira.mongodb.org/browse/SERVER-828 SERVER-828. Похоже, что он добавлен в последнее подразделение 2.1 (разработка): это означает, что он будет доступен для производства, когда выпускаются версии 2.2.

Ответ 3

Если это встроенный массив, то вы не можете напрямую извлекать его элементы. Полученный документ будет иметь форму пользователя (корневой документ), хотя не все поля могут быть заполнены (в зависимости от вашего запроса).

Если вы хотите получить только этот элемент, вы должны сохранить его как отдельный документ в отдельной коллекции. Он будет иметь одно дополнительное поле, user_id (может быть частью _id). Тогда это тривиально делать то, что вы хотите.

Пример документа может выглядеть так:

{
    _id: {user_id: ObjectId, item_id: "1234"},
    name: "some item"
}

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