几天来,我一直在使用Neo4j图形数据库开发一个新闻feed,并玩弄各种方法,包括一个活动日志(类似于Facebook),将跟踪每个用户的动作。
例如,User1向User2发送一个好友请求(在Cypher中会转换成类似这样的内容):
MATCH
(me:User {username: 'john.snow@gmail.com'}),
(friend:User {username: 'arya.stark@gmail.com'})
WHERE
NOT (me)-[:FRIENDSHIP_UPDATE]-(:FriendshipStatus)-[:FRIENDSHIP_UPDATE]-(friend)
CREATE
(me)-[:FRIENDSHIP_UPDATE]-(friendshipStatus:FriendshipStatus {status: 0})-[:FRIENDSHIP_UPDATE]->(friend)
RETURN
me,
friendshipStatus,
friend
到目前为止非常基本的东西,只需创建2个关系和1个节点,其中包含有关他们友谊的所有信息。
检索传出和传入事件也非常简单:
MATCH
(me:User {username: 'john.snow@gmail.com'})-[actionName]->(actionData)-[]->(friend:User)
RETURN
me,
type(actionName) AS actionName,
actionData,
friend
UNION MATCH
(me:User)<-[actionName]-(actionData)<-[]-(friend:User)
RETURN
me,
type(actionName) AS actionName,
actionData,
friend
但是,假设User2拒绝了User1的好友请求,这将最终删除他们之间的整个关系。没有问题…对于一个简单的通知面板(如"你有一个好友请求",另一个取消好友请求,"oups,没有好友请求")。所以,没有历史。
就像我说的,我打算做一些类似Facebook活动日志的事情。
> You liked [User]'s*link to the user* [Photo]*link to the photo* at [Time].
> [User]*link to user* declined your friend request at [Time].
> You sent [User]*link to user* a friend request at [Time]
我已经尝试了各种方法来做到这一点,包括链表,直到一天。然后,日期将包含用户在特定日期执行或暴露的事件(当创建事件时,它也被推送到朋友时间轴-参见第二个代码块),并保持用户之间的直接关系(友谊更新,点赞等),以便速度,因此我不必搜索所有的日期节点。
编辑:忘了说为什么我没有坚持那个特定的设计。问题在于操作之间没有相似性(例如,"喜欢"指向"帖子",而"友谊请求"指向"用户"),这使我最终得到了多个不想要的连接。
什么是一个好的数据库设计来跟踪所有这些操作,即使它们被删除?提前感谢。
一个有用的事件日志必须不删除任何日志条目,并且必须可靠地返回带有原始数据的条目。从本质上讲,日志条目是静态数据,一旦创建就不能更改。
- 也许最好的解决方案是为所有事件维护一个单独的"日志数据库"(甚至可能不是一个图形数据库)的日志条目。这将使您的"实时数据"数据库更简单,并且您的日志记录机制也将更简单。
- 如果你想使用相同的neo4j DB日志条目,你可以保持它在一个单独的"日志子图",从你的"实时数据子图"不相交(即,没有共享节点,和"日志节点"one_answers"活动节点"之间没有关系——尽管日志属性可以包含识别信息关于实时数据)。它必须是不相交的,因为活动数据可以随时更改(例如,节点/关系可以被删除,属性可以更改,等等),但是日志条目必须仍然能够返回在创建条目时应用的数据状态。然而,这种方法可能比它的价值更多的努力。