我尝试做的是写一个查询 - 我已经把它作为一个web服务(在本地机器上工作,所以我得到了名字和人作为参数) - 它连接了拥有相同爱好的人和将爱好设置为关系属性作为数组。 我的第一次尝试是;
MERGE (aa:Person{name:$name})
WITH aa, $people as people
FOREACH (person IN people |
MERGE (bb:Person{name:person.name})
MERGE (bb)-[r:SHARESSAMEHOBBY]->(aa)
ON MATCH SET r.hobbies = r.hobbies + person.hobby
ON CREATE SET r.hobbies = [person.hobby])
然而,这导致重复的属性元素,如["游泳","游泳"]
我试图只设置唯一的属性。然后我尝试了以下查询;
MERGE (aa:Person{name:$name})
WITH aa, $people as people FOREACH (person IN people | MERGE (bb:Person{name:person.name}) MERGE (bb)-[r:SHARESSAMEHOBBY]->(aa)
WITH r, COALESCE(r.hobbies, []) + person.hobby AS hobbies
UNWIND hobbies as unwindedHobbies
WITH r, collect(distinct, unwindedHobbies) AS unique
set r.as = unique)
但是现在它给了我语法错误;
errorMessage = "[Neo.ClientError.Statement.SyntaxError] Invalid use of WITH inside FOREACH
感谢任何帮助。
答案 0 :(得分:0)
这应该有效:
MERGE (aa:Person {name: $name})
WITH aa
UNWIND $people AS person
MERGE (bb:Person {name: person.name})
MERGE (bb)-[r:SHARESSAMEHOBBY]-(aa)
WITH r, person, CASE
WHEN NOT EXISTS(r.hobbies) THEN {new: true}
WHEN NOT (person.hobby IN r.hobbies) THEN {add: true}
END AS todo
FOREACH(ignored IN todo.new | SET r.hobbies = [person.hobby])
FOREACH(ignored IN todo.add | SET r.hobbies = r.hobbies + person.hobby);
您实际上有2个问题,上述查询同时解决了这两个问题:
如果SHARESSAMEHOBBY
关系已存在于相反的方向(从aa
到bb
),则以下MERGE
子句会导致不必要的创建第二个SHARESSAMEHOBBY
关系(从bb
到aa
):
MERGE(bb) - [r:SHARESSAMEHOBBY] - >(aa)
为了避免这种情况,您应该使用非方向关系模式(MERGE
允许,但不允许CREATE
)来匹配任一方向的关系,如下所示:
MERGE(bb) - [r:SHARESSAMEHOBBY] - (aa)
您需要确定是否有必要初始化新的hobbies
列表或将person.hobby
值添加到尚未具有该值的现有r.hobbies
列表中。上面的查询使用CASE
子句分配给todo
NULL
或带有键的地图,指示要执行的其他工作。然后,它会使用FOREACH
子句来执行每个要执行的操作。