我习惯拥有以前作为关系数据库家伙正在进行的活动的表格。我想知道如何在neo4j数据库中存储交易,日志或其他任何信息。让#s假设我有一个帐户,该帐户已分配给用户A:
(u:User {name:"A"})
我想跟踪他所做的交易,例如扣除或增加价值:
(t:Transaction {value:"-20", date:timestamp()})
我是否会为每个事务做一个新节点并将其分配给用户:
(u) -[r:changeBalance]-> (t)
最后,我可能有许多分配给用户的节点,并且每个节点保留一个事务,导致许多节点只有一个信息。我在思考一个对最后50个事务有限制的查询(限制50,按t.date排序)可能仍然必须读取所有可用的事务节点以在限制适用之前获得总排序队列 - 这似乎有点不可思议
您如何为neo4j数据库中的操作列表建模?任何提示都非常感激。
答案 0 :(得分:1)
If you used a simple query like the following, you would NOT be reading all Transaction
nodes per User
.
MATCH (u:User)-[r:ChangeBalance]->(t:Transaction)
RETURN u, t
ORDER BY t.date;
You'd only be reading the Transaction
nodes that are directly related to each User
(via a ChangeBalance
relationship). So, the performance would not be as bad as you are afraid it might be.
答案 1 :(得分:1)
虽然您的查询一切正常 - 您只阅读与此特定用户相关的交易 - 这种方法可以改进。
让我们假设,由于某种原因,您的应用程序将工作5年,并且您拥有每天有10笔交易的用户。这将导致~18250事务连接到单个节点。
从数据模型的角度来看,这不是一个好主意。在这种情况下,如果您想在某个非索引字段上过滤结果(获取50个最新事务),那么这将导致完整的18250节点遍历。
这可以通过向数据库添加其他关系来解决。
目前您有这样的图表:(user)-[:HAS]->(transasction)
( user )
/ | \
(transasction1) (transaction2) (transaction3)
您可以在交易之间添加其他关系,以指定事件的序列。
就像那样:(transaction)-[:NEXT]->(transasction)
( user )
/ | \
(transasction1)-(transaction2)-(transaction3)
注意:不需要额外的PREVIOUS
关系,因为Neo4j在两个方向上存储关系指针,因此向后遍历可以与前进相同的速度完成。
并保持与第一次和最后一次用户交易的关系:
(user)-[:LAST_TRANSACTION]->(transaction)
(user)-[:FIRST_TRANSACTION]->(transaction)
这允许您在1跳中获得最后一笔交易。最后50个额外的50个跃点。
因此,增加额外的复杂性,您可以更有效地遍历/操纵数据。
这个想法来自EventStore数据库(和它们类似)。
此外,利用这样的数据模型,可以通过包装事务序列来加强用户平衡。这可以为您提供一种快速,快捷的方式来随时获得用户平衡。
在此模型中获取最新的50个事务可能如下所示:
MATCH (user:User {id: 1} WITH user
MATCH (user)-[:LAST_TRANSACTION]->(last_transaction:Transaction) WITH last_transaction
MATCH (last_transasction)<-[:NEXT*0..50]-(transasctions:Transaction)
RETURN transactions
获得用户总余额可以是:
MATCH (user:User {id: 1}) WITH user
MATCH (user)-[:FIRST_TRANSACTION]->(first_transaction:Transaction) WITH first_transaction
MATCH (first_transaction)-[:NEXT*]->(transactions:Transaction)
RETURN first_transaction.value + sum(transasctions.value)