JF *_*ier 8 java graph neo4j cypher
假设我在neo4j中有一个节点的属性"名称".现在我想通过识别具有相同名称的所有节点来强制执行给定名称的最多一个节点.更准确地说:如果有三个名称为"dog"的节点,我希望它们只被一个名为"dog"的节点替换,其中:
其背景如下:在我的图中,通常有几个同名的节点应被视为"相等"(尽管有些节点具有比其他节点更丰富的属性信息).把a.name = b.name在WHERE子句是极其缓慢.
编辑:我忘了提到我的Neo4j目前是版本2.3.7(我无法更新).
第二个编辑:节点和可能的弧有一个已知的标签列表.节点的类型是已知的.
第三次编辑:我想从Java调用上面的"节点崩溃"过程,因此Cypher查询和过程代码的混合也将是一个有用的解决方案.
我认为您需要类似节点的同义词。
1)遍历所有节点并创建节点同义词:
MATCH (N)
WITH N
MERGE (S:Synonym {name: N.name})
MERGE (S)<-[:hasSynonym]-(N)
RETURN count(S);
Run Code Online (Sandbox Code Playgroud)
2)仅删除一个节点的同义词:
MATCH (S:Synonym)
WITH S
MATCH (S)<-[:hasSynonym]-(N)
WITH S, count(N) as count
WITH S WHERE count = 1
DETACH DELETE S;
Run Code Online (Sandbox Code Playgroud)
3)其余同义词(带有apoc)的传输属性和关系:
MATCH (S:Synonym)
WITH S
MATCH (S)<-[:hasSynonym]-(N)
WITH [S] + collect(N) as nodesForMerge
CALL apoc.refactor.mergeNodes( nodesForMerge );
Run Code Online (Sandbox Code Playgroud)
4)撕下Synonym标签:
MATCH (S:Synonym)<-[:hasSynonym]-(N)
CALL apoc.create.removeLabels( [S], ['Synonym'] );
Run Code Online (Sandbox Code Playgroud)
我用以下模式制作了一个测试用例:
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)
Run Code Online (Sandbox Code Playgroud)
什么导致以下输出:
其中节点 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;
Run Code Online (Sandbox Code Playgroud)
结果输出如下所示:
必须指出的是,您必须知道各种关系的类型。
所有属性都从具有“较高”ID 的节点复制到具有“较低”ID 的节点。