Neo4j,Cypher:条件创建

5

我有一个特定的问题,要创建一个有条件的创建语句。我不能在这里使用 MERGE,因为 MATCHCREATE 语句是不同的。以下是查询语句..

....
WITH m
OPTIONAL MATCH (x)-[r1:FeedNext{user_id:USER_ID}]->(m)-[r2:FeedNext{user_id:USER_ID}]->(y) 
WHERE x IS NOT NULL AND y IS NOT NULL 
WITH x, y, m, r1, r2
CREATE (x)-[:FeedNext{user_id:USER_ID}]->(y) 
DELETE r1, r2 
RETURN m 

xy都为null时,返回0行。

在同样的情况下运行时,m不会返回null

....
WITH m
OPTIONAL MATCH (x)-[r1:FeedNext{user_id:USER_ID}]->(m)-[r2:FeedNext{user_id:USER_ID}]->(y) 
RETURN m 

在所有情况下返回m的值,有什么解决方法?


我不明白,你的第二个查询中,“x”和“y”是null,但“m”不是?你可以在console中展示一下吗? - jjaderberg
一般情况下,您的 WHERE 条件通过确保 x 和 y 不为 NULL,从而限制 CREATE 语句的执行,但是如果这样,RETURN 子句也将不会被执行。如果您想要返回是否已创建,您必须仅过滤 CREATE 子句,例如在 FOREACH 中进行创建,并使用一个在某种情况下为空并在另一种情况下包含 x、y 的集合。 - jjaderberg
@jjaderberg 是的,完全正确。实际上,m是这个查询中来自前一个查询的输入,我忘了提到(对此很抱歉)。我会在问题中更新这个信息。 - red-devil
明白了。我可以分享一个技巧,虽然有点绕,也许其他人可以提供更好的建议。 - jjaderberg
好的,谢谢。请翻译。 - red-devil
2个回答

10

你的 WHERE 条件通过确保 xy 不为 NULL,限制了 CREATE 从而使得其永远不会执行,但是如果这样做,则也不会到达 RETURN 子句。如果你想要返回是否创建,你必须仅过滤 CREATE 子句。一种方法是在 FOREACH 子句中创建并删除,FOREACH 子句接受集合,你可以通过让集合为空来过滤一种情况,而在另一种情况下包含 x,y。通过嵌套 FOREACH,你可以像这样做。

....
WITH m
OPTIONAL MATCH (x)-[r1:FeedNext {user_id:{USER_ID}}]->(m)-[r2:FeedNext {user_id:{USER_ID}}]->(y)
FOREACH (a IN CASE WHEN x IS NULL THEN [] ELSE [x] END | 
    FOREACH (b IN CASE WHEN y IS NULL THEN [] ELSE [y] END | 
        CREATE a-[:FeedNext { user_id:{USER_ID}}]->b
        DELETE r1, r2
    )
)
RETURN m

我刚刚尝试了这个查询,但是它出现了以下错误 Neo.DatabaseError.Statement.ExecutionFailure,并且在尝试使用 CREATE UNIQUE 时会抛出 expecting 'a' to be be node but it's a null - red-devil
它对我有效。这是一个控制台http://console.neo4j.org/r/bjotdo。执行`MATCH(m{uid:“m”})`以获取`m`,然后粘贴我的查询并将`{USER_ID}`参数替换为`1`。 - jjaderberg
我也在控制台上尝试了一下。当r1和r2不存在时,它会抛出“Error: java.lang.NullPointerException”错误。这是截图 https://drive.google.com/file/d/0B2XvzrkA012sLXNTVnctTEVwcWM/edit?usp=sharing - red-devil
你说得对,我脑抽了。Coalesce 不会返回一个空集合,而是返回第一个非空值或者如果没有则返回 null,所以只有在 xy 都不为 null 时才能使用。然而,原则是正确的,我更新了我的答案,使用 CASE 来获取空集合。想试试吗? - jjaderberg

0
如果你想根据条件进行匹配,这是我使用的一种解决方法。希望能对你有所帮助。
OPTIONAL MATCH b2p = (x1)-[r1:FeedNext {user_id:{USER_ID}}]->(m1)
OPTIONAL MATCH b2c = (x2)-[r2:FeedNext {email_id:{EMAIL_ID}}]->(m2)
FOREACH (usertype IN CASE WHEN {USER_TYPE} = 'B2P' AND b2p is not null THEN [1] ELSE [] END | MERGE x1-[:ORDER]->(or:Order{order_id:{ORDER_ID}}))
FOREACH (usertype IN CASE WHEN {USER_TYPE} = 'B2C' AND b2c is not null THEN [1] ELSE [] END | MERGE x2-[:ORDER]->(or:Order{order_id:{ORDER_ID}}))

这里的 {USER_TYPE} 是一个输入参数,它是有条件选择合并路径的。

谢谢


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接