我正在使用neo4j-javascript-driver
我遇到了问题。
我创建了一个节点脚本,用Users
和Event
填充数据库(我不认为脚本与问题相关)。
db就像(u:User)-[:LatestEvent]->(e1:Event)-[:Prev]->(e2:Event)-[:Prev].....
当尝试运行脚本来创建1个具有3个事件的用户时,我没有得到我试图创建的链表,我认为这是因为我在不等待其他人的情况下触发请求是查询:
MATCH (user:User {id: {userId})
OPTIONAL MATCH (user)-[r:LatestEvent]->(prev:Event)
DELETE r
MERGE (user)-[:LatestEvent]->(event:Event)
ON CREATE SET event={event}
MERGE (user)-[:Posted]->(event)
FOREACH(y IN CASE WHEN prev IS NULL THEN [] ELSE [1] END | MERGE (event)-[:Prev]->(prev))
WITH DISTINCT event
RETURN DISTINCT properties(event) as event
db中的结果不一致我看到3个事件连接到具有LatestEvent
关系的用户,而另一个我看到2或4。
我认为导致这个问题的原因是,在执行此查询时,我不会等待先前的查询返回,而是再次发生在现实世界中可能发生的事情。
任何解决方案?
答案 0 :(得分:0)
好吧,所以在玩了一下之后,我想你实际上可以把它拉掉。您当前的问题是,在执行任何操作以锁定.data
节点以及链接列表之前,您尝试找到df = pd.DataFrame(dict(A=[1, 2, 3, 4],
B=[7.5, 7, 5, 4.5],
C=[0, 1, 1, 0]))
colors = {0: 'red', 1: 'aqua'}
plt.scatter(df.A, df.B, c=df.C.map(colors))
。因此,每个异步查询都在其自己的事务中匹配prev
。下一行:User
,将强制查询序列化,但它们已经分别定位并分配了prev
。你可以通过在查询的绝对开始时在DELETE
节点上获取写锁来解决这个问题,如下所示:
prev
原始查询中的一些更改:
1)通过在顶部包含:User
,您的查询将做的唯一事情是在必须获取写锁之前找到MATCH (user:User {id: {userId} })
SET user.id = user.id
WITH user
MERGE (user)-[r:LatestEvent]->(prev)
ON CREATE SET prev:Root
DELETE r
CREATE (user)-[:LatestEvent]->(event:Event)
SET event={event}
MERGE (user)-[:Posted]->(event)
MERGE (event) - [:Prev] -> (prev)
RETURN event
,这将强制它们序列化其余的查询。因此,一个查询将提交,下一个获取锁的查询可以读取生成的新SET user.id = user.id
。
2)而不是折磨:User
逻辑,:Event
节点中的OPTIONAL MATCH...FOREACH(CASE...)
,如果没有先前MERGE
,它将使节点成为prev
节点。这也可以通过提供固定的结尾来更轻松地按顺序获取整个链表::Event
3)您只创建一个事件,不需要对其应用:Root
。返回MATCH p = (:User {id: x}) - [:LatestEvent|:Prev*] -> (:Root) RETURN [x IN NODES(p) WHERE x:Event] AS event_list
而不是DISTINCT
也不会节省太多带宽,并且您将丢失一些数据(标签,内部ID等),但如果您丢失了PROPERTIES(event)
我更喜欢用Cypher而不是javascript来处理它。
您可以阅读有关neo4j隔离here的更多信息。