MongoDB поддерживает многофункциональные документы, которые могут включать, среди прочего, встроенные документы. Эта функция довольно хорошо воплощает отношение has-a и может, при правильном моделировании, уменьшить количество операций поиска, необходимых для определения определенных данных, поскольку в Mongo нет соединений.
Классическим примером встраивания коллекции документов в родительский документ являются контактные адреса (например, почтовые адреса, электронная почта, твиттер и т. Д.), Связанные с человеком. Думай визитки. Конечно, вы можете смоделировать это любым количеством способов — в традиционном реляционном мире это будет отношение один ко многим, по крайней мере, между двумя таблицами. Тем не менее, с базой данных, ориентированной на документы, вы можете моделировать родительский документ со встроенной коллекцией contacts
, каждый из которых является документом, содержащим, скажем, тип (например, телефон, твиттер, электронная почта) и значение (которое может быть 555-555- 555, @jon_doe и т. Д.).
Эти отношения с Mongo работают хорошо, если дочерний внедренный документ никогда не должен существовать вне его родителя . Например, в случае визитной карточки контактный документ, представляющий номер телефона, не обязательно имеет смысл вне контекста лица, которому он принадлежит. Благодаря этим отношениям вы можете легко найти конкретного человека по его / ее номеру телефона (то есть, с помощью языка запросов Монго, вы можете легко получить доступ к внутренним массивам через его точечное представление ). И, когда у вас есть справка к человеку, вам не нужно выполнять серию находок, чтобы выяснить контактную информацию — все в порядке.
Тем не менее, вещи начинают быстро становиться болезненными, если вы хотите работать исключительно с отдельным вложенным документом. То есть, если вы выполняете находки, предназначенные для работы с ожидаемым результирующим внедренным документом, вас ожидает некоторая работа: начиная с Mongo 2.2, вы не можете выбрать отдельный документ из коллекции, находящейся в родительском объекте, через запрос. Находка в этом случае потянет все — это зависит от вас (то есть вашего приложения), чтобы отфильтровать вещи.
Пример, вероятно, поможет: представьте пример визитной карточки из более раннего документа — person
содержащего встроенную коллекцию contacts
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
{ first_name: 'Andrew' , last_name: 'Glover' , contacts: [ { type: 'cell' , value: '555-555-5555' , last_updated: 2012 - 09 - 01 23 : 41 : 51 UTC }, { type: 'home' , value: '555-555-5551' , last_updated: 2012 - 02 - 11 12 : 21 : 11 UTC } ] } |
Найти этот документ по номеру телефона легко:
1
|
db.persons.find({ 'contacts.value' : '555-555-5555' }) |
Но что, если вы хотите найти недавно обновленный contact
, скажем, с начала месяца, и изменить его значение или добавить дополнительные метаданные? Запрос, который вы хотели бы выглядеть примерно так:
1
|
db.persons.find({ 'contacts.last_updated' : {$gte: datetime( 2012 , 8 , 1 )}}) |
При желании вы можете добавить ограничители запросов (например, {contacts:1}
), которые будут просто возвращать документ пользователя только с набором contacts
. Таким образом, вам остается перебирать итоговую коллекцию contacts
и работать со своей магией таким образом. То есть вам все еще нужно найти контактный документ, который был отредактирован в этом месяце! В вашем коде!
Ничего страшного, говоришь? Этот конкретный пример, действительно, немного надуманен; однако представьте, если общий документ достаточно большой (может быть, это не person
а organization
!) и что встроенная коллекция также длинна (сколько сотрудников у Google?). Теперь это простое обновление протягивает много байтов по проводам (и в процессе обременяет Монго), а затем ваше приложение работает с большим количеством байтов в памяти (теперь документ облагает налогом ваше приложение!). Вы хотели, чтобы эта операция происходила быстро и под нагрузкой?
Таким образом, в случае встроенных коллекций документов, если вы предполагаете работать с конкретным встроенным документом изолированно , на данном этапе лучше смоделировать взаимосвязи с различными коллекциями (т. Е. В этом примере жизнь будет намного проще, если есть person
коллекция и contacts
). Действительно, гибкость ориентированных на документы хранилищ данных без схем является благом для быстрой эволюционной разработки. Но вы все еще должны подумать заранее. Если, конечно, вы не мазохист.
Я большой поклонник Монго. Ознакомьтесь с некоторыми из статей, видео и подкастов, которые я сделал, которые посвящены Монго, в том числе:
- Разработка Java 2.0: MongoDB: хранилище данных NoSQL с (все в порядке) перемещениями СУБД
- Демонстрация видео: введение в MongoDB
- Элиот Горовиц на MongoDB
- Стив Франсия из 10gen говорит о MongoDB
Ссылка: MongoDB Из окопов: врезанные мазохистские коллекции от нашего партнера JCG Эндрю Гловера в блоге The Disco Blog .