Подтвердить что ты не робот

Моделирование дружеских отношений в MongoDB

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

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

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

4b9b3361

Ответ 1

Я недавно спросил Элиота Горовица в этом же вопросе на конференции MontoDB 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'});

Ответ 2

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

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

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

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

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

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

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

Ответ 3

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

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

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