Neo4j 如何从某个起始节点递归删除节点
Neo4j how to delete nodes recursively from some start node
在我的 Neo4j 数据库中,我有以下实体:
@NodeEntity
public class Product {
private final static String CONTAINS = "CONTAINS";
private final static String DEFINED_BY = "DEFINED_BY";
private final static String VOTED_FOR = "VOTED_FOR";
private final static String PARENT = "PARENT";
private final static String CREATED_BY = "CREATED_BY";
@GraphId
private Long id;
@RelatedTo(type = PARENT, direction = Direction.INCOMING)
private Product parent;
@RelatedTo(type = CONTAINS, direction = Direction.OUTGOING)
private Set<Product> childProducts = new HashSet<>();
@RelatedTo(type = DEFINED_BY, direction = Direction.INCOMING)
private Set<Criterion> criterias = new HashSet<>();
@RelatedTo(type = VOTED_FOR, direction = Direction.INCOMING)
private Set<Vote> votes = new HashSet<>();
@RelatedTo(type = CREATED_BY, direction = Direction.OUTGOING)
private User user;
}
@NodeEntity
public class Criterion {
private final static String CREATED_BY = "CREATED_BY";
private final static String DEFINED_BY = "DEFINED_BY";
@GraphId
private Long id;
@RelatedTo(type = DEFINED_BY, direction = Direction.OUTGOING)
private Product owner;
@RelatedTo(type = CREATED_BY, direction = Direction.OUTGOING)
private User user;
}
@NodeEntity
public class Vote {
private static final String VOTED_ON = "VOTED_ON";
private final static String VOTED_FOR = "VOTED_FOR";
private static final String CREATED_BY = "CREATED_BY";
@GraphId
private Long id;
@RelatedTo(type = VOTED_FOR, direction = Direction.OUTGOING)
private Product product;
@RelatedTo(type = VOTED_ON, direction = Direction.OUTGOING)
private Criterion criterion;
@RelatedTo(type = CREATED_BY, direction = Direction.OUTGOING)
private User user;
}
Product
是一个复合实体,可以包含子 Products
。
从层次结构中的某个 Product
节点开始,我需要删除此 Product
上的所有 Votes
,然后我需要递归删除所有子 Products
、Criteria
定义通过这些节点和 Votes
。 User
个节点不能删除.
我试过这个 Cypher 查询:
MATCH (p:Product)-[r:CONTAINS*]-(e) WHERE id(p) = {productId} FOREACH (rel IN r| DELETE rel) DELETE e
但它只删除产品,不删除起始节点上的投票以及所有子条件和投票。请帮助我进行正确的 Cypher 查询。谢谢。
我将其分成两个查询。第一个向下递归收集产品层次结构,第二个删除一个产品节点及其直接环境。
获取产品层次结构很简单:
MATCH (p:Product)-[:CONTAINS*]->(childProduct)
WHERE id(p) = {productId}
RETURN id(childProduct) as id
要删除一个产品,我们需要删除该产品节点的所有关系。此外,如果所有相关节点既不是用户(您想保留它们)也不是产品(想想父产品 - 它们也应该保留),则也需要删除它们。我们还需要确保目标节点没有连接,这就是为什么第二个可选匹配:
MATCH (p:Product)
OPTIONAL MATCH (p)-[r]-(t)
WHERE id(p) = {productId}
DELETE r,p
WITH t
OPTIONAL MATCH (t)-[r2:VOTE_ON|:CREATED_BY]->()
WHERE none(x in labels(t) WHERE x in ["User", "Product"])
DELETE t,r2
我没有亲自测试这个查询,因为你没有提供测试图。所以把这个当成一个idea,修改直到可行。
更新
在一次聊天中我们发现这个cypher语句解决了问题,注意Product
已经被模型中的Decision
标签所取代:
MATCH (p:Decision)
WHERE p.name = "NoSQL"
WITH p
OPTIONAL MATCH (p)-[r]-(t)
DELETE p,r
WITH t,r
OPTIONAL MATCH (t)-[r2:VOTED_ON|:CREATED_BY|:VOTED_FOR]-()
WITH t, r2,r
WHERE none(x in labels(t) WHERE x in ["User", "Decision"])
DELETE t,r2
在我的 Neo4j 数据库中,我有以下实体:
@NodeEntity
public class Product {
private final static String CONTAINS = "CONTAINS";
private final static String DEFINED_BY = "DEFINED_BY";
private final static String VOTED_FOR = "VOTED_FOR";
private final static String PARENT = "PARENT";
private final static String CREATED_BY = "CREATED_BY";
@GraphId
private Long id;
@RelatedTo(type = PARENT, direction = Direction.INCOMING)
private Product parent;
@RelatedTo(type = CONTAINS, direction = Direction.OUTGOING)
private Set<Product> childProducts = new HashSet<>();
@RelatedTo(type = DEFINED_BY, direction = Direction.INCOMING)
private Set<Criterion> criterias = new HashSet<>();
@RelatedTo(type = VOTED_FOR, direction = Direction.INCOMING)
private Set<Vote> votes = new HashSet<>();
@RelatedTo(type = CREATED_BY, direction = Direction.OUTGOING)
private User user;
}
@NodeEntity
public class Criterion {
private final static String CREATED_BY = "CREATED_BY";
private final static String DEFINED_BY = "DEFINED_BY";
@GraphId
private Long id;
@RelatedTo(type = DEFINED_BY, direction = Direction.OUTGOING)
private Product owner;
@RelatedTo(type = CREATED_BY, direction = Direction.OUTGOING)
private User user;
}
@NodeEntity
public class Vote {
private static final String VOTED_ON = "VOTED_ON";
private final static String VOTED_FOR = "VOTED_FOR";
private static final String CREATED_BY = "CREATED_BY";
@GraphId
private Long id;
@RelatedTo(type = VOTED_FOR, direction = Direction.OUTGOING)
private Product product;
@RelatedTo(type = VOTED_ON, direction = Direction.OUTGOING)
private Criterion criterion;
@RelatedTo(type = CREATED_BY, direction = Direction.OUTGOING)
private User user;
}
Product
是一个复合实体,可以包含子 Products
。
从层次结构中的某个 Product
节点开始,我需要删除此 Product
上的所有 Votes
,然后我需要递归删除所有子 Products
、Criteria
定义通过这些节点和 Votes
。 User
个节点不能删除.
我试过这个 Cypher 查询:
MATCH (p:Product)-[r:CONTAINS*]-(e) WHERE id(p) = {productId} FOREACH (rel IN r| DELETE rel) DELETE e
但它只删除产品,不删除起始节点上的投票以及所有子条件和投票。请帮助我进行正确的 Cypher 查询。谢谢。
我将其分成两个查询。第一个向下递归收集产品层次结构,第二个删除一个产品节点及其直接环境。
获取产品层次结构很简单:
MATCH (p:Product)-[:CONTAINS*]->(childProduct)
WHERE id(p) = {productId}
RETURN id(childProduct) as id
要删除一个产品,我们需要删除该产品节点的所有关系。此外,如果所有相关节点既不是用户(您想保留它们)也不是产品(想想父产品 - 它们也应该保留),则也需要删除它们。我们还需要确保目标节点没有连接,这就是为什么第二个可选匹配:
MATCH (p:Product)
OPTIONAL MATCH (p)-[r]-(t)
WHERE id(p) = {productId}
DELETE r,p
WITH t
OPTIONAL MATCH (t)-[r2:VOTE_ON|:CREATED_BY]->()
WHERE none(x in labels(t) WHERE x in ["User", "Product"])
DELETE t,r2
我没有亲自测试这个查询,因为你没有提供测试图。所以把这个当成一个idea,修改直到可行。
更新
在一次聊天中我们发现这个cypher语句解决了问题,注意Product
已经被模型中的Decision
标签所取代:
MATCH (p:Decision)
WHERE p.name = "NoSQL"
WITH p
OPTIONAL MATCH (p)-[r]-(t)
DELETE p,r
WITH t,r
OPTIONAL MATCH (t)-[r2:VOTED_ON|:CREATED_BY|:VOTED_FOR]-()
WITH t, r2,r
WHERE none(x in labels(t) WHERE x in ["User", "Decision"])
DELETE t,r2