MongoDB或Neo4J,用于参与事件M:M关系的用户



以下是我的简化模型:

User{ String name, Set<UserEvent>, double[] coordinates }
UserEvent{ Event event, Boolean isGoing, Boolean isMaybeGoing }
Event { String name, Set<User> goingUsers, Set<User> maybeGoingUsers, double[] coordinates }

我很困惑我将如何实现它以及使用哪个DB。

  • 我需要MongoDB来实现地理定位功能findUsersNearEvent(Event event) / findEventsNearUser(User user)

  • 但我认为Neo4J更适合用户和事件之间的关系,还有不同类型用户的问题:去还是可能去。为此,我创建了UserEvent,但我不知道它是否是一个好的设计。

如果有人有一个好的设计解决方案,或者可以建议我用什么做什么,那就太好了。

对于Neo4j,"UserEvent"将是用户和事件之间的关系。

我可能会用两种关系类型来建模:

(:User)-[:GOING]->(:Event)
(:User)-[:MAYBE_GOING]->(:Event)

你可以使用Neo4j Spatial在Neo4j中进行空间搜索,请参阅Max的博客文章介绍,他为餐馆做了类似的事情。

查询可能看起来像:

START event = node:events("withinDistance(lat,lon,distance)")
MATCH (event)<-[rsvp:GOING|:MAYBE_GOING]-(user)
RETURN event.name, user.name,type(rsvp)

更新:(:用户)-[:朋友]->(:用户

实际上,用户之间会有这种情况,从一个用户到另一个事件,这是没有意义的。您可以随心所欲地将查询结果投影到域对象中。

您可以使用两种关系类型:FRIEND和:FRIEND_REQUEST

然后也可以在查询中使用它,例如,如果你也想邀请用户的朋友。

START event = node:events("withinDistance(lat,lon,distance)")
MATCH (event)<-[rsvp:GOING]-(user)-[:FRIEND]-(friend)
RETURN event.name, user.name,type(rsvp), collect(friend.name) as friends

或者,如果你想向用户展示他可能要参加的活动,他的哪些朋友已经参加了。

START event = node:events("withinDistance(lat,lon,distance)")
MATCH (event)<-[rsvp:MAYBE_GOING]-(user)
OPTIONAL MATCH (user)-[:FRIEND]-(friend)-[:GOING]->(event)
RETURN event.name, user.name,type(rsvp), collect(distinct friend.name) as friends_going

Michael Hunger已经发布了Neo4j的示例。为了完整起见,我将解释如何使用MongoDB解决此问题。

在MongoDB中,您将有一个集合events,并将参与用户存储在每个文档的数组中。

 {
      name:"Event Name",
      location: { type: "Point", coordinates: [ 40, 5 ] },
      attendees: [
           { name: "Alice", status:"maybe" },
           { name: "Bob", status:"sure" },
           { name: "Charlie", status:"sure" }
      ]
 }

这个模式假设用户名是唯一的和不可变的。如果不是,则除了名称之外,还将使用引用用户的_id。为什么是另外而不是相反?因为MongoDB不支持联接,所以应该镜像多个文档中的信息以避免嵌套查询。理想情况下,您最频繁的查询应该通过检索单个文档来满足。当您想要一个事件的参与者列表时,十六进制字符串列表可能不太有用。因此,在查找活动时,您希望看到的有关与会者的任何信息都应该嵌入到活动文档中。

然后,用户将在第二个集合中。您可能决定将每个参与关系保留两次(一次在事件文档中,一次在用户文档中)。或者不是。这取决于用例的频率:列出用户的事件或列出事件的用户。

最新更新