Как связать данные в 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 () операция над строковым документом, чтобы гарантировать, что когда многие записывают в этот документ происходит, целостность данных по-прежнему сохраняется.
в рамках этой операции я бы рекомендовал использовать следующие операторы:
- при добавлении владельца, $addToSet для предотвращения дублирования
- при удалении владельца, $ pull
оба описаны здесь: http://docs.mongodb.org/manual/reference/operators/#update-operators-array