Моделирование отношений друг с другом в MongoDB - PullRequest
17 голосов
/ 13 сентября 2011

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

  • Извлечь все идентификаторы друзей из пользователя doc
  • Извлечьвсе массивы друзей из пользовательских документов этих друзей (используя $ in для всех идентификаторов друзей), объединить сторону приложения в один набор, а затем объединить его с идентификаторами друзей первого уровня, чтобы получить набор всех друзей и друзей друзей
  • Используйте этот набор для выполнения окончательного запроса (с использованием $ in) для всех друзей и друзей друзей

Хотя это довольно просто, по сравнению с огромным количеством возвратно-поступательных сообщенийк тому, что мы могли бы сделать с объединением в реляционной базе данных.Есть ли более эффективный способ сделать это в MongoDB или эта проблема лучше всего подходит для СУРБД?

Ответы [ 3 ]

13 голосов
/ 06 января 2012

Я задал этот же вопрос Элиоту Горовицу недавно на конференции MongoDB SV.Он сказал, что он будет структурировать это, чтобы хранить друзей каждого пользователя как вложенные документы внутри каждого пользователя.Например, структура может выглядеть следующим образом:

{
  _id : ObjectId("4e77bb3b8a3e000000004f7a"),
  username : "alex",
  friends : ["283956723823626626aa", "226567377578888888as", "8738783888aas88a8a88" ]
}

, тогда вы можете иметь индекс для user.friends

http://www.mongodb.org/display/DOCS/Indexes#Indexes-IndexingArrayElements

"Когда сохранено значение документапоскольку поле ключа индекса - это массив, MongoDB индексирует каждый элемент массива. Для получения дополнительной информации см. страницу Multikeys. "

, поэтому, чтобы найти всех друзей" alex ", я могу просто сделать:

db.user.find ({'friends': '4e77bb3b8a3e000000004f7a'});

7 голосов
/ 13 сентября 2011

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

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

Однако, с точки зрения «полной выполненной работы», это не очень отличается от того, что вы бы сделали с SQL. Да, это относительно простой запрос SQL, но сам сервер по-прежнему должен выполнять в основном ту же работу, отдавать или отбирать некоторый сетевой трафик.

Есть ли более эффективный способ сделать это в MongoDB или эта проблема лучше всего подходит для СУБД?

Есть ли лучший способ в MongoDB? Возможно нет. Но «самостоятельное соединение» в SQL не может легко масштабироваться на нескольких серверах. Фактически, попытка сделать это на нескольких серверах в основном превращается в процесс, аналогичный процессу MongoDB.

Технически, эту работу лучше всего выполнять с помощью базы данных графов, которая не является ни MongoDB, ни RDBMS.

Для графических баз данных вы можете взглянуть на Trinity для .NET или NEO4J .

2 голосов
/ 13 сентября 2011

Я полагаю, что это то, что лучше обрабатывается СУБД (БД с графическим запретом), поскольку вам явно необходимо выполнить операцию соединения.Хотя СУБД могла бы реализовать это таким же образом, она могла бы реализовать объединение более эффективно и распределять информацию более эффективно, чем MongoDB.

С учетом сказанного, накладные расходы на выполнение запроса "соединения" атомарно могут оказаться слишком дорогостоящимиесли у вас большой кластер узлов db и огромное количество пользователей.

Если вас не беспокоит согласованность и атомарность запроса, и все, что вам нужно, - это предотвращать переход туда-сюда междуприложение и БД, вы можете написать функцию JavaScript, которая будет выполнять весь запрос на MongoDB, или использовать операцию MapReduce для более эффективных распределенных запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...