#mongodb #neo4j #nosql #data-modeling #graph-databases
#mongodb #neo4j #nosql #моделирование данных #графические базы данных
Вопрос:
У меня проблема с моделированием данных в MongoDB. Документация, похоже, не предлагает решений, которые работали бы в моем случае.
Мой конкретный вариант использования очень похож на систему друзей Facebook. У меня есть коллекция пользователей, и каждый пользователь может подключаться к другим пользователям, отправляя приглашения, которые либо принимаются, либо отклоняются.Этот механизм будет основополагающим для других функций, таких как вычисление общих друзей, рекомендация наиболее адекватных друзей и т. Д.
Казалось бы, популярными решениями были бы:
- Встраивание идентификаторов друзей в пользовательский документ в виде массива
- Встраивание данных друзей в пользовательский документ в виде массива
Но это проблематично — если у кого-то несколько тысяч друзей, то производительность пострадает, а производительность важна для меня.
Моя идея состояла в том, чтобы создать отдельную коллекцию, в которой каждый документ был бы соединением между двумя пользователями. В этом документе могут быть встроенные данные каждого пользователя и соответствующие дополнительные данные, например статус приглашения на подключение. Что вы думаете об этом дизайне?
Кроме того, существуют ли какие-либо проверенные методы обработки таких ситуаций в MongoDB, когда производительность имеет решающее значение? Я также открыт для других предложений dbs, я думал о графических dbs.
Ответ №1:
Этот вариант использования было бы легко обработать в графической базе данных, такой как neo4j.
Например, вы могли бы использовать язык Cypher от neo4j для хранения факта, что пользователь 123 создал приглашение и отправил его нескольким пользователям таким образом:
MATCH (u:User {id: 123})
CREATE (u)-[:CREATED]->(i:Invitation {id: 999, text: '...', date: ..., location: ...})
UNWIND [234, 345, 456] AS inviteeId
MATCH (u1:User {id: inviteeId})
CREATE (i)-[:INVITED]->(u1)
И всякий раз, когда пользователь отвечает, вы можете сохранить его следующим образом:
MATCH (u:User {id: 345}), (i:Invitation {id: 999})
CREATE (u)-[:RESPONDED {accept: false}]->(i)
Наконец, чтобы увидеть отдельных пользователей, которые приняли любое из приглашений пользователя 123:
MATCH (u:User {id: 123})-[:CREATED]->(:Invitation)<-[:RESPONDED {accept: true}]-(acceptor:User)
RETURN DISTINCT acceptor