отношения многие ко многим для социального приложения: Mongodb или графовые базы данных, такие как Neo4j - PullRequest
2 голосов
/ 15 февраля 2012

Я пытался понять встраивание в Mongodb, но не смог найти достаточно хорошую документацию.Связывать не рекомендуется, поскольку записи не являются атомарными в разных документах, а также есть два поиска.Кто-нибудь знает, как решить эту проблему, или вы предложите мне перейти на график dbs, например, neo4j.

Я пытаюсь создать приложение, которое будет нуждаться в отношениях «многие ко многим».Чтобы объяснить, я возьму пример библиотеки.Он может предлагать пользователю книги на основе книг, которые читают его друзья и читают соседи (как единомышленники).

Есть пользователи и книги.Пользователи заимствуют книги и имеют друзей, которые являются другими пользователями

  1. Для данного пользователя мне нужны все книги, которые он читает, и количество общих друзей для книги
  2. Для данной книги мне нужновсе люди, которые читают это.Может быть предоставлен пользователю A, это вернет пересечение людей, читающих книгу, и друзей пользователя A. Это взаимная дружба

Users = [

       { name: 'xyz', 'id':'000000', friend_ids:['949583','958694']}

       { name: 'abc', 'id':'000001', friend_ids:['949582','111111']}

      ]

Books = [

      {'book':'da vinci code', 'author': 'dan brown', 'readers'=['949583', '000000']}

      {'book':'iCon', 'author': 'Young', 'readers'=['000000', '000001']}

      ]

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

Правильно ли я моделирую свои данные?Может ли это быть эффективно сделано в mongodb или я должен посмотреть на график ДБ.

Ответы [ 2 ]

6 голосов
/ 15 февраля 2012

Отказ от ответственности: я работаю на Neo4j

Из вашего плана, требований и типа данных кажется, что ваше приложение скорее в сладости для графовых баз данных.

Я бы посоветовал вам сделать быстрый всплеск с базой данных графов и посмотреть, как это происходит.

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

Некоторые вопросы:

  • Почему вы выбрали MongoDB в первую очередь?
  • Какой язык реализации вы используете?
5 голосов
/ 16 февраля 2012

Ваше предложение базовой схемы, описанное выше, будет хорошо работать для MongoDB с несколькими предложениями:

  1. Используйте целые числа для идентификаторов, а не для строк.Целые числа часто будут храниться более компактно в MongoDB (они всегда будут 8 байтами, тогда как хранимый размер строк будет зависеть от длины строки).Вы можете использовать findAndModify для эмуляции уникальных генераторов последовательностей (например, auto_increment в некоторых реляционных базах данных) - см. SequenceField Mongoengine для примера того, как это делается.Вы также можете использовать ObjectIds , которые всегда равны 12 байтам, но практически гарантированно являются уникальными, не сохраняя никакой информации о координации в базе данных.
  2. Вместо этого следует использовать поле _idid, так как это поле всегда присутствует в MongoDB и для него создан уникальный индекс по умолчанию.Это означает, что ваши _id всегда уникальны, а поиск по _id очень быстр.

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

  1. "Для пользователя мне нужны все книги, которые он читает и сколькообщих друзей за книгуа.Найдите нужного пользователя, затемб.запросить коллекцию книг, используя db.books.find({_id: {$in: [list, of, books, for, the, user]}}), затемс.Для каждой книги вычислите объединение наборов для читателей этой книги и друзей пользователя
  2. «Учитывая книгу, мне нужны все люди, которые ее читают».а.Найдите книгу, о которой идет речь, затемб.Найдите всех пользователей, которые читают эту книгу, снова используя $in, например db.users.find({_id: {$in: [list, of, users, reading, book]}})
  3. «Может быть получен пользователь A, это вернет пересечение людей, читающих книгу, и друзей пользователя A.»а.Найдите нужного пользователя, затемб.Найдите книгу, о которой идет речь, затемс.Вычисление совокупности наборов друзей пользователя и читателей книги

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

В качестве альтернативы использованию $in для некоторых из этих запросов вы можете создать индекс в массиве.и запросите в коллекции документы с определенным значением в массиве.Например, для вышеприведенного запроса # 1 вы можете выполнить:

// create an index on the array field "readers"
db.books.ensureIndex({readers: 1})

// now find all books for user whose id is 1234
db.books.find({readers: 1234})

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

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