Neo4j:使用可选关系实现软删除

Neo4j:使用可选关系实现软删除,neo4j,cypher,soft-delete,Neo4j,Cypher,Soft Delete,我正在尝试在Neo4j中实现一个软删除。从Alice的角度来看,Cypher中描述的图表如下: (clyde:User)<-[:FOLLOWS]-(alice:User)-[:LIKES]->(bob:User) 我的第一次查询尝试是: match (user:User {Id: 1}) optional match (user)-[follows:FOLLOWS]->(subject) remove user:User set user:_User delete follo

我正在尝试在Neo4j中实现一个软删除。从Alice的角度来看,Cypher中描述的图表如下:

(clyde:User)<-[:FOLLOWS]-(alice:User)-[:LIKES]->(bob:User)
我的第一次查询尝试是:

match (user:User {Id: 1})
optional match (user)-[follows:FOLLOWS]->(subject)
remove user:User set user:_User
delete follows
create (user)-[:_FOLLOWS]->(subject);
match (user:User {Id: 1})
remove user:User set user:_User
optional match (user)-[follows:FOLLOWS]->(subject)
foreach (f in filter(f in collect({r: follows, n: subject}) where f.r is not null) | delete f.r create (user)-[:_FOLLOWS]->(f.n));
问题是,当该用户没有跟踪任何人时,查询会尝试在
user
null
之间创建一个关系,因为第二个匹配是可选的,所以它会给出以下错误:
其他节点为null。

我的第二次尝试是:

match (user:User {Id: 1})
optional match (user)-[follows:FOLLOWS]->(subject)
remove user:User set user:_User
delete follows
create (user)-[:_FOLLOWS]->(subject);
match (user:User {Id: 1})
remove user:User set user:_User
optional match (user)-[follows:FOLLOWS]->(subject)
foreach (f in filter(f in collect({r: follows, n: subject}) where f.r is not null) | delete f.r create (user)-[:_FOLLOWS]->(f.n));
所以我把关系和主题放在一张地图上,把这些地图收集到一个集合中,扔掉所有的“空”地图,在集合中循环。但是这个查询给了我一个错误:

SyntaxException: Invalid input '.': expected an identifier character, node labels, a property map, whitespace or ')' (line 1, column 238)
有人知道我怎么解决这个问题吗

谢谢,
Jan

您能否先更改标签,然后匹配关系?然后,您应该能够使用“非可选”匹配,而不必处理没有后续关系的情况,比如

MATCH (user:User {Id: 1})
REMOVE user:User SET user:_User
WITH user
MATCH (user)-[follows:FOLLOWS]->(subject)
DELETE follows
CREATE (user)-[:_FOLLOWS]->(subject)
MATCH (user:User {Id: 1})
OPTIONAL MATCH (user)-[follows:FOLLOWS]->(subject)
REMOVE user:User SET user:_User
WITH user, follows, subject
WHERE subject IS NOT NULL
DELETE follows
CREATE (user)-[:_FOLLOWS]->(subject)
或者您可以携带用户、关注和主题,并在主题不为空的位置进行筛选。差不多

MATCH (user:User {Id: 1})
REMOVE user:User SET user:_User
WITH user
MATCH (user)-[follows:FOLLOWS]->(subject)
DELETE follows
CREATE (user)-[:_FOLLOWS]->(subject)
MATCH (user:User {Id: 1})
OPTIONAL MATCH (user)-[follows:FOLLOWS]->(subject)
REMOVE user:User SET user:_User
WITH user, follows, subject
WHERE subject IS NOT NULL
DELETE follows
CREATE (user)-[:_FOLLOWS]->(subject)
编辑:
如果问题是你想为不止一种关系这样做,那么你可以试试

MATCH (user:User {Id: 1})
REMOVE user:User SET user:_User
WITH user 
MATCH (user)-[f:FOLLOWS]->(other)
DELETE f 
CREATE (user)-[:_FOLLOWS]->(other)
WITH user LIMIT 1 
MATCH (user)-[l:LIKES]->(other)
DELETE l 
CREATE user-[:_LIKES]->(other)
您可以继续使用其他关系类型扩展它,只需确保在携带时限制
user
,因为多个匹配项
(user)-[r]>(other)
意味着用户有多个结果,否则您将多次运行下一个查询部分

我不认为在cypher中有一种通用的方法可以做到这一点,因为您无法动态构建关系类型(即
CREATE(a)-[newRel:“\u”+type(oldRel)]->(b)
不起作用)


你是在寻找这样的东西,还是我误解了你的问题?

我认为如果用户之间只有一种关系,即只有
:FOLLOWS
,这种方法是有效的。但在我的例子中,实际上还有更多的,例如
:LIKES
,也必须被替换。例如,如果一个用户没有
:遵循
关系,并且至少有一个
:喜欢
关系,我认为我无法承载该用户。不确定您的意思。您的问题是关于处理查询中可选匹配的空案例(“问题是…”),这就是我的回答。当然,我应该更清楚。我希望能够替换多种关系类型,包括可选的和必需的。当用户没有:FOLLOWS关系时,您的解决方案不起作用,因为它使用的是精确匹配,并且没有用户结转到:LIKES部分,因为它在:FOLLOWS部分中不匹配。这正是我最初使用可选匹配的原因,但这导致了原始问题中的两个错误。