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

时间:2013-12-16 08:08:28

标签: neo4j cypher soft-delete

我正在尝试在Neo4j中实现软删除。从爱丽丝的观点来看Cypher中描述的图表是这样的:

(clyde:User)<-[:FOLLOWS]-(alice:User)-[:LIKES]->(bob:User)

我没有实际删除节点及其关系,而是

  1. 更改其标签,以便无法再直接查找,即删除其User标签并添加_User标签(请注意下划线)
  2. 替换其关系,以便我的常规查询无法再访问它,例如删除其:FOLLOWS关系并将其替换为:_FOLLOWS关系。
  3. 因此,这基本上相当于将行移动到关系数据库中的归档表。我认为这是一种非常有效的方法,因为您实际上从未访问过已被软删除的图形部分。此外,您不必修改任何现有查询。

    软删除Alice的结果应该是:

    (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);
    

    问题是,当此用户没有关注任何人时,查询会尝试在usernull之间创建关系,因为第二个匹配是可选的,因此它会给我这个错误:{{ 1}}

    我的第二次尝试是:

    Other node is null.

    所以我将关系和主题放入地图中,将这些地图收集在一个集合中,将每个“空”地图扔掉并循环到集合上。但是这个查询给了我这个错误:

    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));
    

    有谁知道如何解决这个问题?

    谢谢, 扬

1 个答案:

答案 0 :(得分:2)

您可以先更改标签然后匹配关系吗?那么你应该能够使用'非可选'匹配,而不必处理没有以下关系的情况,比如

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:"_"+type(oldRel)]->(b)不起作用)

这就是你想要的东西,还是我误解了你的问题?