Neo4j Cypher-有条件的比赛比赛

时间:2018-12-10 18:32:11

标签: neo4j cypher cypher-3.1

我有一个数据库,其中包含用户(u:User {id: 1}),用户状态(us:UserStatus {status: 'pending'})及其之间的关系(u)-[hs:HAS_STATUS {from: 1541030400, to: 4102444800}]->(us)

用户状态可以为"pending""active""suspended"2100-01-01是将来的某个日期,表示用户仍然具有此状态。

我正在尝试运行一个查询,该查询通过创建具有新状态的新关系来更新用户的状态,并通过将to属性设置为当前日期来存档旧关系。

这是我尝试过的:

MERGE (u:User { id: 1 })
WITH u
MATCH (u)-[hs1:HAS_STATUS]->(us1:UserStatus)
WHERE us1.status <> 'active' AND hs1.to > 1544400000
SET hs1.to = 1544400000
MERGE (us2:UserStatus {status: 'active'})
MERGE (u)-[hs2:HAS_STATUS {from: 1544400000, to: 4102444800}]->(us2)

如果用户已经具有满足WHERE子句的状态,则将其存档并创建新的状态关系。但是,如果用户尚未具有状态,则SET子句(按预期方式)将被跳过,但是两条MERGE行也会被跳过。如何确保无论合并如何执行它们?

编辑: 原始查询有一些错字。

2 个答案:

答案 0 :(得分:1)

[这会回答您的最新问题]

如果匹配失败,则MATCH(不带OPTIONAL限定符)将中止其余查询。

此查询显示了一种匹配模式的方法,如果匹配成功,可以选择执行写操作,如果匹配失败,则不中止查询的其余部分:

MERGE (u:User { id: 1 })
FOREACH(hs IN
  [(u)-[hs1:HAS_STATUS]->(us1:UserStatus)
        WHERE us1.status <> 'active' AND hs1.to > 1544400000 | hs1] |
  SET hs.to = 1544400000)
MERGE (us2:UserStatus {status: 'active'})
MERGE (u)-[hs2:HAS_STATUS {from: 1544400000, to: 4102444800}]->(us2);

此查询使用FOREACH子句遍历匹配hs1值的列表(在这种情况下,大小为0或1),并将每个to的值设置为1544400000。该列表由pattern comprehension生成。即使列表为空,其余查询仍将执行。

答案 1 :(得分:0)

编辑:由于您说查询中使用的“日期”实际上是一个纪元秒的替代品,因此删除了上一个答案片段。

如果未更改任何行,那么将发生以下两种情况之一。

  1. 您的MATCH(带有关联的WHERE)找不到任何匹配的模式。您应该尝试只运行该MATCH和WHERE来查看它是否返回任何行。

  2. 您要合并的关系已经存在。您可能想要尝试匹配这两个节点之间的关系(具有这些属性),并查看它是否已经存在。