合并节点

APOC 库包含一个可用于合并节点的存储过程。

此过程允许将节点列表合并到列表中的第一个节点上(所有关系也会合并到该节点上)。可以全局和/或单独指定属性的合并行为。

合并节点的存储过程

限定名称 类型

apoc.refactor.mergeNodes(nodes LIST<NODE>, config MAP<STRING, ANY>) - 将给定的 LIST<NODE> 合并到 LIST<NODE> 中的第一个 NODE 上。所有 RELATIONSHIP 值也会合并到该 NODE 上。

过程

MATCH (p:Person)
WITH p ORDER BY p.created DESC // newest one first
WITH p.email AS email, collect(p) as nodes
CALL apoc.refactor.mergeNodes(nodes, {properties: {
    name:'discard',
    age:'overwrite',
    kids:'combine',
    `addr.*`: 'overwrite',
    `.*`: 'discard'
}})
YIELD node
RETURN node

配置选项

以下是此过程的配置选项:这些配置选项也适用于 apoc.refactor.mergeRelationships([rels],{config})

type 操作

discard

如果第一个节点中已设置属性,则保留该属性,否则写入列表中的第一个属性

overwrite / override

列表中的最后一个属性胜出

combine

如果列表中只有一个属性,则将其设置/保留为单个属性,否则创建一个数组,并尝试强制转换值

此外,mergeNodes 支持以下配置属性

type 操作

mergeRels

true/false:允许合并具有相同类型和方向的关系。

produceSelfRel

true/false:如果为 true(默认),则插入由合并到目标节点的节点所产生的任何新的自引用关系,否则不插入。请注意,此参数独立于 mergeRels 配置,且不会影响预先存在的自引用关系(在这种情况下使用 preserveExistingSelfRels 配置)。

preserveExistingSelfRels

true/false:仅在 mergeRels:true 时有效。如果为 true(默认),最终节点中预先存在的自引用关系将保留,否则将被删除。

singleElementAsArray

false/true:如果为 false(默认)且 typecombine,当两个数组合并后的新数组大小为 1 时,它会提取出单个值。

配置映射中未包含名称的属性将被覆盖。

关系属性使用相同的方法进行管理,除非配置映射为 null,在这种情况下,实体属性会被合并。

示例

以下示例将进一步解释此过程。

相同的起始和结束节点

以下内容创建了一个包含具有相同起始和结束节点的关系的图
CREATE (n1:Person {name:'Tom'}),
(n2:Person {name:'John'}),
(n3:Company {name:'Company1'}),
(n5:Car {brand:'Ferrari'}),
(n6:Animal:Cat {name:'Derby'}),
(n7:City {name:'London'}),

(n1)-[:WORKS_FOR {since:2015}]->(n3),
(n2)-[:WORKS_FOR {since:2018}]->(n3),
(n3)-[:HAS_HQ {since:2004}]->(n7),
(n1)-[:DRIVE {since:2017}]->(n5),
(n2)-[:HAS {since:2013}]->(n6);
return *;
apoc.refactor.mergeNodes.createDataSetFirstExample
以下内容将 John 和 Tom 合并为一个节点
MATCH (a1:Person{name:'John'}), (a2:Person {name:'Tom'})
WITH head(collect([a1,a2])) as nodes
CALL apoc.refactor.mergeNodes(nodes,{properties:"combine", mergeRels:true})
YIELD node
RETURN count(*)

如果运行上述查询,将得到以下图形

apoc.refactor.mergeNodes.resultFirstExample

由于这些关系具有相同的起始和结束节点,因此关系被合并,属性被组合。

不同的起始和结束节点

以下内容创建了一个包含具有不同起始或结束节点的关系的图
Create (n1:Person {name:'Tom'}),
(n2:Person {name:'John'}),
(n3:Company {name:'Company1'}),
(n4:Company {name:'Company2'}),
(n5:Car {brand:'Ferrari'}),
(n6:Animal:Cat {name:'Derby'}),
(n7:City {name:'London'}),
(n8:City {name:'Liverpool'}),
(n1)-[:WORKS_FOR{since:2015}]->(n3),
(n2)-[:WORKS_FOR{since:2018}]->(n4),
(n3)-[:HAS_HQ{since:2004}]->(n7),
(n4)-[:HAS_HQ{since:2007}]->(n8),
(n1)-[:DRIVE{since:2017}]->(n5),
(n2)-[:HAS{since:2013}]->(n6)
return *;
apoc.refactor.mergeNodes.createDataSetSecondExample
以下内容将 John 和 Tom 合并为一个节点
MATCH (a1:Person{name:'John'}), (a2:Person {name:'Tom'})
WITH head(collect([a1,a2])) as nodes
CALL apoc.refactor.mergeNodes(nodes,{
    properties:"combine",
    mergeRels:true
})
YIELD node
RETURN count(*)

如果运行上述查询,将得到以下图形

apoc.refactor.mergeNodes.resultSecondExample
apoc.refactor.mergeNodes.resultSecondExampleData

由于关系具有不同的结束节点,因此保留了所有关系和属性。