Как связать данные в MongoDB?

Я храню строку в базе данных вместе с владельцами строки (один или несколько владельцев на строку).

Я всегда работал с MySQL, который является обычной реляционной базой данных. В этом случае я бы сохранил строку вместе с уникальным идентификатором в одной таблице, а затем уникальный идентификатор строки вместе с владельцами (как несколько записей) во второй таблице.

затем я мог бы получить строки владельцами, используя SQL-соединение.

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

будет ли это считаться неправильным при работе с базами данных NoSQL? Не следует ли мне думать в терминах "отношений" при работе с NoSQL?

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

{
    "string": "foobar",
    "owners": [
        "owner1",
        "owner2",
        "owner3"
    ]
}

однако в этом случае я не уверен, как я буду искать "все строки, принадлежащие owner1".

4 ответов


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

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


будет ли это считаться неправильным при работе с базами данных NoSQL? Не следует ли мне думать в терминах "отношений" при работе с NoSQL?

есть так много вопросов о случае вложения, и это сводится к так мало.

что-то, что не было упомянуто здесь, что нужно учитывать, если вы хотите вставить:

  • будет ли размер документа увеличиваться массово? Если да, то документ может часто перемещаться по диску, это плохо.
  • будет ли связанная строка иметь много присоединений к коллекции, над которой я работаю (т. е. video не удается вставить user). В этом случае могут возникнуть проблемы при копировании избыточных данных из связанной строки во вложенный документ, особенно при обновлении этих избыточных данных.
  • как мне нужно будет отобразить эти результаты?

отображение результатов всегда является ключевым решающим фактором в Ли или нет внедрять. Если вам нужно разбить на страницы большое количество строк, скажем 1000, вам нужно будет использовать $slice оператор в обычном запросе или в рамках агрегации. В 1000 я признаю, что это может быть довольно быстро, но рано или поздно операция в памяти станет медленнее, чем обычный запрос (infact это всегда должно быть).

Если вам требуется сложная сортировка и отображение вложенных документов, вы можете разделить их и вместо этого иметь структуру документа из:

{
    "string": "foobar",
    "owners": [
        ObjectId(),
        ObjectId(),
        ObjectId()
    ]
}

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

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

возвращаясь к сложной сортировки и разбиения на страницы. С помощью этих данных вы можете, конечно, получить все owner идентификаторы с одной туда и обратно, а затем в другой туда и обратно вы можете запросить эти строки владельцев внутри the users таблица с обычным запросом с помощью $in возможность для комплексного просмотра.

таким образом, эта структура в целом, как я обнаружил, очень эффективна.

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

надеюсь, это поможет, и я не ходил по кругу,


чтобы дополнить ответ dbaseman:

Да, ваш подход выглядит хорошо. Вы можете легко найти "все строки, принадлежащие owner1"

db.collection.find({owners: 'author1'})

это возможно, потому что mongodb обрабатывает массивы особым образом.


при работе со встроенными данными я бы рекомендовал ознакомиться с поведением атомарности в mongo. Хорошей отправной точкой будет здесь : http://docs.mongodb.org/manual/core/data-modeling/#atomicity

в вашем конкретном случае при добавлении / удалении пользовательского ObjectId (как рекомендовано Sammaye) в массив "владельцы", вы захотите использовать a findAndModify () операция над строковым документом, чтобы гарантировать, что когда многие записывают в этот документ происходит, целостность данных по-прежнему сохраняется.

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

  1. при добавлении владельца, $addToSet для предотвращения дублирования
  2. при удалении владельца, $ pull

оба описаны здесь: http://docs.mongodb.org/manual/reference/operators/#update-operators-array