Поддокументы Mongoose против вложенной схемы


122

Мне любопытно узнать о плюсах и минусах использования вложенных документов по сравнению с более глубоким слоем в моей основной схеме:

var subDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [subDoc]
});

или

var mainDoc = new Schema({
  names: [{
    name: String
 }]
});

В настоящее время я использую вложенные документы повсюду, но в первую очередь меня интересуют проблемы с производительностью или запросы, с которыми я могу столкнуться.


Я пытался ввести вам ответ, но не мог найти как. Но взгляните сюда: mongoosejs.com/docs/subdocs.html
gustavohenke

Вот хороший ответ о соображениях MongoDB, которые следует задать себе при создании схемы базы данных: stackoverflow.com/questions/5373198/…
anthonylawson

Вы имели в виду, что нужно еще и _idполе описать ? Я имею в виду, что он не автоматический, если он включен?
Vadorequest

кто-нибудь знает _id, уникальны ли области вложенных документов? (создано с использованием 2-го способа в вопросе OP)
Сайтама

Ответы:


72

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

Альтернативный синтаксис объявления

Новое в версии 3 Если вам не нужен доступ к экземпляру схемы вложенного документа, вы также можете объявить вложенные документы, просто передав литерал объекта [...]


1
Но я пробовал это. Почему данные субдокументов не хранятся в отдельной коллекции. Он всегда хранится в коллекции mainDoc.
Fizer Khan

17
вот как работают дополнительные документы. они встраиваются внутрь документа. прежде чем играть с мангустом, убедитесь, что вы понимаете, что такое MongoDB.
AndyL

1
Что касается добавления _id в схему, это имеет смысл, но я создал схему с массивом вложенных документов и массивом объектных литералов, и к обоим был добавлен _id. Изменилось ли поведение?
Дрю Гудвин,

@DrewGoodwin, похоже, так было какое-то время: stackoverflow.com/questions/17254008/…
cheesemacfly

37

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


4
Это отличный ответ. Иногда я использую вложенные документы в нескольких моделях или у меня есть два поля в модели, которые нужно различать, но при этом структура вложенных документов остается одинаковой.
Мартин Халлен

2
вам также следует учитывать преимущества / недостатки сохранения избыточной информации.
Sam Vloeberghs

25

Вы должны использовать встроенные документы, если это статические документы или их не более нескольких сотен из-за снижения производительности. Я уже говорил об этой проблеме некоторое время назад. Недавно Ася Камский, которая работает архитектором решений для MongoDB, написала статью об «использовании вложенных документов».

Я надеюсь, что это поможет тем, кто ищет решения или передовой опыт.

Оригинальный пост на http://askasya.com/post/largeembeddedarrays . Вы можете получить доступ к ее профилю stackoverflow на https://stackoverflow.com/users/431012/asya-kamsky

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

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

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

Наиболее очевидная проблема с этим состоит в том, что в конечном итоге вы достигнете предела документа в 16 МБ, но это совсем не то, о чем вам следует беспокоиться. Документ, который постоянно растет, будет нести все более высокие затраты каждый раз, когда его необходимо перемещать на диск, и даже если вы предпримете шаги для смягчения последствий фрагментации, ваши записи в целом будут излишне длинными, что повлияет на общую производительность всего вашего приложения.

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

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


3
Это должен быть главный ответ; это удар по деньгам. Собственные официальные документы MongoDB говорят примерно то же самое.
Джей Эдвардс,

Эта статья о шаблоне Bucket дополняет то, о чем хорошо говорит Ася. mongodb.com/blog/post/building-with-patterns-the-bucket-pattern Я думаю, что схема subDoc в вопросе OP будет хорошо работать с шаблоном Bucket.
plong0 03

13

По сути, создайте переменную nestedDovи поместите ее сюдаname: [nestedDov]

Простая версия:

var nestedDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [nestedDoc]
});

Пример JSON

{
    "_id" : ObjectId("57c88bf5818e70007dc72e85"),
    "name" : "Corinthia Hotel Budapest",
    "stars" : 5,
    "description" : "The 5-star Corinthia Hotel Budapest on the Grand Boulevard offers free access to its Royal Spa",
    "photos" : [
        "/photos/hotel/corinthiahotelbudapest/1.jpg",
        "/photos/hotel/corinthiahotelbudapest/2.jpg"
    ],
    "currency" : "HUF",
    "rooms" : [
        {
            "type" : "Superior Double or Twin Room",
            "number" : 20,
            "description" : "These are some great rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/2.jpg",
                "/photos/room/corinthiahotelbudapest/5.jpg"
            ],
            "price" : 73000
        },
        {
            "type" : "Deluxe Double Room",
            "number" : 50,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 92000
        },
        {
            "type" : "Executive Double Room",
            "number" : 25,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 112000
        }
    ],
    "reviews" : [
        {
            "name" : "Tamas",
            "id" : "/user/tamas.json",
            "review" : "Great hotel",
            "rating" : 4
        }
    ],
    "services" : [
        "Room service",
        "Airport shuttle (surcharge)",
        "24-hour front desk",
        "Currency exchange",
        "Tour desk"
    ]
}

Пример:

введите описание изображения здесь


1
Это вообще не решает вопроса о производительности.
cyberwombat 02

Я немного отредактировал, чтобы было больше смысла. Что вы думаете?
Уэйн Чиу

3
Вопрос не в том, как делать вложенные схемы. Обсуждается, будет ли Mongoose более производительным с вложенными схемами или вложенными суб-документами. В основном мы говорим о тестах, сортировках или крайних случаях, когда Mongoose предпочитает одно другому. И, как упоминается в выбранном ответе, это, похоже, не имеет никакого значения, по крайней мере, с V3.
cyberwombat 02

17
Возможно, не работает для OP, но я нашел это очень полезным. Спасибо.
Джин Хиггинс,

Это хорошо, когда все 3 схемы объявлены в одном файле .js, как мы можем справиться с этим, если они объявлены в 3 разных файлах .js?
Satyam

9

Я думаю, что это обрабатывается в другом месте в нескольких сообщениях на SO.

Немного:

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


3
Возможно, я неправильно формулирую свой вопрос - это не вопрос о том, как я должен структурировать свою базу данных, а скорее о том, как использовать подсхему вместо того, чтобы просто писать массив на более глубоком уровне. Моя основная причина использования подсхемы заключается в том, что я могу использовать настраиваемые типы схем и проверять их - то, что не работает с вложенными массивами (из предыдущего вопроса, который я задавал по SO). Насколько я могу судить, вложенный документ почти такой же, как и вложенный массив - я просто не знаю его внутреннего устройства - если их использование приведет к проблемам с производительностью или тому подобное.
cyberwombat

0

Между ними есть некоторая разница:

  • Использование вложенной схемы полезно для проверки.

  • Вложенную схему можно повторно использовать в других схемах.

  • Вложенная схема добавляет во вложенный документ поле _id, если вы не использовали "_id: false"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.