我们说我有一个属性"名称" neo4j中的节点。现在我想通过识别具有相同名称的所有节点来强制执行给定名称的最多一个节点。更确切地说:如果有三个节点名称是" dog",我希望它们只被一个名为" dog"的节点替换,其中:
背景如下:在我的图表中,通常有几个同名的节点应被视为"等于" (尽管有些人拥有比其他人更丰富的财产信息)。将a.name = b.name
置于WHERE子句中的速度非常慢。
第二次编辑:节点和可能的弧有一个已知的标签列表。节点的类型是已知的。
第三次编辑:我想在上面打电话"节点崩溃"来自Java的程序,因此Cypher查询和程序代码的混合也将是一个有用的解决方案。
答案 0 :(得分:4)
我认为你需要类似节点的同义词。
1)浏览所有节点并创建节点同义词:
MATCH (N)
WITH N
MERGE (S:Synonym {name: N.name})
MERGE (S)<-[:hasSynonym]-(N)
RETURN count(S);
2)仅使用一个节点删除同义词:
MATCH (S:Synonym)
WITH S
MATCH (S)<-[:hasSynonym]-(N)
WITH S, count(N) as count
WITH S WHERE count = 1
DETACH DELETE S;
3)其余同义词的传输属性和关系(使用apoc
):
MATCH (S:Synonym)
WITH S
MATCH (S)<-[:hasSynonym]-(N)
WITH [S] + collect(N) as nodesForMerge
CALL apoc.refactor.mergeNodes( nodesForMerge );
4)删除Synonym
标签:
MATCH (S:Synonym)<-[:hasSynonym]-(N)
CALL apoc.create.removeLabels( [S], ['Synonym'] );
答案 1 :(得分:4)
我使用以下架构制作了一个测试用例:
CREATE (n1:TestX {name:'A', val1:1})
CREATE (n2:TestX {name:'B', val2:2})
CREATE (n3:TestX {name:'B', val3:3})
CREATE (n4:TestX {name:'B', val4:4})
CREATE (n5:TestX {name:'C', val5:5})
MATCH (n6:TestX {name:'A', val1:1}) MATCH (m7:TestX {name:'B', val2:2}) CREATE (n6)-[:TEST]->(m7)
MATCH (n8:TestX {name:'C', val5:5}) MATCH (m10:TestX {name:'B', val3:3}) CREATE (n8)<-[:TEST]-(m10)
结果如下:
节点B实际上是相同的节点。这是我的解决方案:
//copy all properties
MATCH (n:TestX), (m:TestX) WHERE n.name = m.name AND ID(n)<ID(m) WITH n, m SET n += m;
//copy all outgoing relations
MATCH (n:TestX), (m:TestX)-[r:TEST]->(endnode) WHERE n.name = m.name AND ID(n)<ID(m) WITH n, collect(endnode) as endnodes
FOREACH (x in endnodes | CREATE (n)-[:TEST]->(x));
//copy all incoming relations
MATCH (n:TestX), (m:TestX)<-[r:TEST]-(endnode) WHERE n.name = m.name AND ID(n)<ID(m) WITH n, collect(endnode) as endnodes
FOREACH (x in endnodes | CREATE (n)<-[:TEST]-(x));
//delete duplicates
MATCH (n:TestX), (m:TestX) WHERE n.name = m.name AND ID(n)<ID(m) detach delete m;
结果输出如下:
必须标记您必须知道各种关系的类型。
所有属性都从具有“更高”ID的节点复制到具有“更低”ID的节点。