node.js - пример - npm mongodb




Mongo DB отношения между документами в разных коллекциях (4)

Использование MongoDB со ссылками - это путь к проблемам производительности. Прекрасный пример того, что не использовать. Это отношение m:n где m и n могут масштабироваться до миллионов. MongoDB работает хорошо, где мы имеем 1:n(few) , 1:n(many) , m(few):n(many) . Но не в ситуациях, когда у вас есть m(many):n(many) . Это, очевидно, приведет к двум запросам и большому количеству домашнего хозяйства.

Я еще не готов это отпустить, поэтому я передумал проблему и отредактировал Q (оригинал ниже).

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

У меня три коллекции:

Users
Lists
Texts

Пользователь может иметь тексты и списки - списки «содержат» тексты. Тексты могут быть в нескольких списках.

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

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

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

var TextSchema = new Schema({
      _id: Number,
      name: String,
      inListID: { type : Array , "default" : [] },
      [...]

Также довольно редко бывает, что тексты будут в МНОГИХ списках, поэтому массив не будет взрываться. Вопрос типа остается, хотя, есть шанс, что это масштабы или на самом деле лучший способ реализовать его с помощью mongoDB? Помогло бы ли это ограничить количество списков, текст которых может быть (возможно)? Есть ли рецепт для нескольких: много отношений?

Было бы даже здорово получить ссылки на проекты, где это было сделано и как оно было реализовано (несколько: многие отношения). Я не могу поверить, что все уклоняются от БМ монго, как только нужны некоторые отношения.

Оригинальный вопрос

Я сломаю это в двух проблемах, которые я вижу до сих пор: 1) Предположим, что список состоит из 5 текстов. Как я могу ссылаться на тексты, содержащиеся в списке? Просто откройте массив и сохраните там _ids текста? Похоже, эти массивы могут вырасти до луны и назад, замедляя приложение? С другой стороны, тексты должны быть доступны без списка, поэтому внедрение не является вариантом. Что делать, если я хочу получить все тексты списка, содержащего 100 текстов .. звучит как два запроса и массив со 100 полями: - /. Таким образом, этот способ ссылки на правильный способ сделать это?

var ListSchema = new Schema({
  _id: Number,
  name: String,
  textids: { type : Array , "default" : [] },
  [...]

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

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

Меня также интересуют общие мысли о передовой практике для такого рода ссылок (многие-ко-многим?) И особенно масштабируемости / производительности.


Использование массива в MongoDB обычно не предпочтительнее и обычно не рекомендуется экспертами.

Вот решение, которое пришло мне в голову:

Каждый документ Users всегда уникален. В User могут быть Lists и Texts для отдельного документа. Поэтому в Lists и Texts есть поле для USER ID, которое будет _id Users .

Lists всегда есть владелец в Users поэтому они хранятся как есть.

Владельцем Texts может быть либо « Users либо « List , поэтому вы также должны содержать поле «LIST ID», которое будет _id Lists .

Теперь имейте в виду, что Texts не может иметь идентификатор пользователя и идентификатор LIST, поэтому вам нужно будет поддерживать условие, что должно быть только одно из них, другое должно быть null чтобы мы могли легко узнать, кто является основным владельцем Texts ,


Написание ответа, поскольку я хочу объяснить, как я буду исходить отсюда.

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

Тем более, что я могу уйти с одним запросом (который я сначала, хотя я не мог), который до сих пор даже не требует использования $in , я уверен, что подход будет масштабироваться. В конце концов, это «просто проект на выходные», поэтому, если это не так, и я в конечном итоге переписываю - все в порядке.

С текстовой схемой:

var textSchema = new Schema({
  _id: {type: Number, required: true, index: { unique: true }},
  ...
  inList: { type : [Number] , "default" : [], index: true }
});

Я могу просто получить все тексты в списке с этим запросом, где inList - это индексированный массив, содержащий _ids текстов в списке.

Text.find({inList: listID}, function(err, text) {
  ...      
});

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

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

@mnemosyn: спасибо за ссылку и указав, что это действительно не большое объединение или, другими словами: просто очень простое отношение. Также некоторые цифры о том, как долго выполняются эти сложные операции (из-за аппаратной зависимости), являются большой помощью.
PS: Grüße aus Bielefeld.

То, что я нашел наиболее полезным во время моих собственных исследований, было таким , что Элвин Ричардс также рассказывает о взаимоотношениях «многие ко многим» примерно в мин. 17. Здесь я получил идею сделать одностороннее отношение, чтобы сохранить себе работу, очищающую мертвые ссылки.

Спасибо за помощь, ребята 👍


Я не уверен, что этот вопрос остается актуальным, но у меня есть аналогичный опыт.
Прежде всего, я хочу сказать, что говорит официальная документация mongo:

Используйте встроенные модели данных, когда: у вас есть модель «один-к-одному» или «один-ко-многим».
Для модели «многие-ко-многим» используются отношения с документами.

Я думаю, это ответ), но этот ответ дает много проблем, потому что:

  1. Как уже упоминалось, монго не предоставляет транзакций вообще.
  2. И у вас нет ограничений внешнего ключа.
  3. Даже если у вас есть ссылки ( DBRefs ) между документами, вы столкнетесь с удивительной проблемой, как разыменовать эти документы.

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

Я понятия не имею, как делаются ограничения внешнего ключа, и я ничего не видел в этом направлении в документации по mongo, поэтому я считаю, что это потрясающая задача (и риск для проекта).

И последние ссылки mongo - это не соединение mysql, и вы не получаете все данные из родительской коллекции с данными из дочерней коллекции (например, все поля из таблицы и все поля из объединенной таблицы в mysql), вы получите просто ОТНОШЕНИЕ к другой документ в другой коллекции, и вам нужно будет что-то сделать с этой ссылкой (разыменование). Его можно легко получить в узле путем обратного вызова, но только в том случае, если вам нужен только один текст из одного списка, но если вам нужны все тексты в одном списке - это ужасно, но если вам нужны все тексты в более чем одном списке - это стать кошмаром ...

Возможно, это мой не лучший опыт ... но я думаю, вы должны подумать об этом ...







mongoose