【问题标题】:Neo4j: implementing soft delete with optional relationshipsNeo4j:使用可选关系实现软删除
【发布时间】:2013-12-16 08:08:28
【问题描述】:

我正在尝试在 Neo4j 中实现软删除。从 Alice 的角度来看,Cypher 中描述的图形是这样的:

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

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

  1. 更改其标签使其无法再被直接查找,即删除其User 标签并添加_User 标签(注意下划线)
  2. 替换它的关系,这样我的正常查询就不能再访问它了,例如删除其 :FOLLOWS 关系并将其替换为 :_FOLLOWS 关系。

所以这基本上相当于将一行移动到关系数据库中的归档表中。我认为这是一种非常有效的方法,因为您实际上永远不会访问已软删除的图表部分。此外,您不必修改任何现有查询。

软删除爱丽丝的结果应该是这样的:

(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 之间创建关系,因为第二个匹配是可选的,所以它给了我这个错误: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));

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

SyntaxException: Invalid input '.': expected an identifier character, node labels, a property map, whitespace or ')' (line 1, column 238)

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

谢谢, 一月

【问题讨论】:

    标签: neo4j cypher soft-delete


    【解决方案1】:

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

    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]-&gt;(other)意味着用户有多个结果,否则您将多次运行下一个查询部分.

    我认为在 cypher 中没有通用的方法,因为您无法动态构建关系类型(即 CREATE (a)-[newRel:"_"+type(oldRel)]-&gt;(b) 不起作用)

    您正在寻找类似的东西还是我误解了您的问题?

    【讨论】:

    • 我认为如果用户之间只有一种关系,即只有:FOLLOWS,那么这种关系是可行的。但就我而言,实际上还有更多,例如:LIKES,也必须更换。例如,如果一个用户没有:FOLLOWS关系,并且至少有一个:LIKES关系,我认为我无法承载该用户。
    • 不确定你的意思。您的问题是关于从查询中的可选匹配中处理 null 案例(“问题是……”),这就是我的回答。
    • 当然,我应该更清楚。我希望能够替换多种关系类型,可选的和强制的。当用户没有 :FOLLOWS 关系时,您的解决方案不起作用,因为它使用完全匹配并且没有用户可以转移到 :LIKES 部分,因为它在 :FOLLOWS 部分中不匹配。这正是我首先使用可选匹配的原因,但这导致了原始问题中的两个错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 2016-09-13
    • 2016-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多