apoc.diff.graphs 过程

该过程接受 2 个字符串参数,即 sourcedest,分别代表要进行比较的 2 条查询语句,以及作为第 3 个参数的可选 config 映射。

该过程对 sourcedest 两个图进行比较,并返回以下方面的差异:

  • 相同节点计数

  • 每个标签的相同计数

  • 相同关系计数器

  • 每个关系类型的相同计数

对于 source 图中具有特定标签的每个节点,通过键或内部 ID 在另一个图(dest 图)中查找相同的节点。如果找到,则:* 比较所有标签 * 比较所有属性

请注意,查找节点时会利用现有的约束来寻找等效节点。若要使用内部 ID 查找节点,可以使用 findById:true 配置(见下文)。

对于 source 图中的每段关系,我们将获取该关系的两个节点,并在 dest 图中查看是否存在具有相同属性和相同起始/结束节点的关系。

该过程支持以下 config 参数

表 1. config 参数
名称 (name) type 默认 description(描述)

findById

boolean

false

通过 ID 查找节点,而不是使用现有约束

relsInBetween

boolean

false

如果启用,则在查询返回关系以及开始或结束节点的情况下,考虑其他终端节点。

boltConfig

Map

{}

type:URL(参见下方的 target 参数表)的情况下,为 apoc.bolt.load 提供额外配置

source

Map

{}

见下文

dest

Map

{}

见下文

sourcedest 映射分别应用于第 1 个和第 2 个过程参数,它们可以包含以下键

表 2. source/dest 参数
名称 (name) type 默认 description(描述)

target(目标)

Map

{}

见下文

params

Map

{}

用于传递额外的查询参数

target 参数接受

表 3. target 参数
名称 (name) type 默认 description(描述)

type

Enum[URL, DATABASE]

URL

使用外部 bolt URL 搜索 target 查询(利用 apoc.bolt.load 过程),或者使用同一实例中的另一个数据库(使用 DATABASE

字符串

{}

在配置 type: "URL" 的情况下,我们可以传递 bolt URL;在 type: "DATABASE" 的情况下,我们可以传递目标数据库名称

使用示例

neo4j 中给定此数据集

CREATE CONSTRAINT IF NOT EXISTS FOR (p:Person) REQUIRE p.name IS UNIQUE;
CREATE (m:Person {name: 'Michael Jordan', age: 54});
CREATE (q:Person {name: 'Tom Burton', age: 23})
CREATE (p:Person {name: 'John William', age: 22})
CREATE (q)-[:KNOWS{since:2016, time:time('125035.556+0100')}]->(p);

我们可以比较同一数据库中的 2 个集合

CALL apoc.diff.graphs("MATCH (start:Person) WHERE start.age < $age RETURN start", "MATCH (start:Person) WHERE start.age > $age RETURN start", {source: {params: {age: 25}}, dest: {params: {age: 25}}})
表 4. 结果
difference entityType id sourceLabel destLabel source dest

"Total count"

"Node"

null

null

null

2

1

"Count by Label"

"Node"

null

null

null

{"Person": 2 }

{"Person": 1 }

"Destination Entity not found"

"Node"

1

"Person"

null

{"name": "Tom Burton" }

null

"Destination Entity not found"

"Node"

2

"Person"

null{"name": "John William" }

null

如果我们要在新的 secondDb 数据库中创建另一个数据集

CREATE CONSTRAINT IF NOT EXISTS FOR (p:Person) REQUIRE p.name IS UNIQUE;
CREATE (m:Person:Other {name: 'Michael Jordan', age: 54}),
    (n:Person {name: 'Tom Burton', age: 47}),
    (q:Person:Other {name: 'Jerry Burton', age: 23}),
    (p:Person {name: 'Jack William', age: 22}),
  (q)-[:KNOWS{since:1999, time:time('125035.556+0100')}]->(p);

我们可以在 neo4j 数据库中执行

CALL apoc.diff.graphs("MATCH p = (start:Person)-[rel:KNOWS]->(end) RETURN start, rel, end",
  "MATCH p = (start)-[rel:KNOWS]->(end) RETURN start, rel, end",
  {dest: {target: {type: "DATABASE", value: "secondDb"}}})
表 5. 结果
difference entityType id sourceLabel destLabel source dest

"Destination Entity not found"

"Node"

1

"Person"

null

{"name": "Tom Burton" }

null

"Destination Entity not found"

"Node"

2

"Person"

null

{"name": "John William"}

null

"Destination Entity not found"

"Relationship"

0

"KNOWS"

null

{"start":{"name":"Tom Burton"},"end":{"name":"John William"},"properties":{"time":"12:50:35.556000000+01:00","since":2016}}

null

反之,我们可以从 secondDb 数据库开始比较 2 个数据集

CALL apoc.diff.graphs("MATCH (node:Person) RETURN node",
  "MATCH (node:Person) RETURN node",
  {dest: {target: {type: "DATABASE", value: "neo4j"}}})
表 6. 结果
difference entityType id sourceLabel destLabel source dest

"Total count"

"Node"

null

null

null

6

3

"Count by Label"

"Node"

null

null

null

{"Person": 4, "Other": 2 }

{"Person": 3 }

"Different Labels"

"Node"

0

"Person"

"Person"

["Other", "Person"]

["Person"]

"Different Properties"

"Node"

1

"Person"

"Person"

{"age": 47 }

{"age": 23 }

"Destination Entity not found"

"Node"

2

"Person"

null

{"name": "Jerry Burton" }

null

"Destination Entity not found"

"Node"

7

"Person"

null

{"name": "Jack William" }

如果我们创建另一个具有与 seconddb 相同数据集的 dbms 实例,我们可以利用 apoc.bolt.load 比较这两个图

CALL apoc.diff.graphs("MATCH p = (start:Person)-[rel:KNOWS]->(end) RETURN start, rel, end", "MATCH p = (start)-[rel:KNOWS]->(end) RETURN start, rel, end", {dest: {target: {type: "URL", value: "<MY_BOLT_URL>"}}})
表 7. 结果
difference entityType id sourceLabel destLabel source dest

"Destination Entity not found"

"Node"

1

"Person"

null

{"name": "Tom Burton" }

null

"Destination Entity not found"

"Node"

2

"Person"

null

{"name": "John William"}

null

"Destination Entity not found"

"Relationship"

0

"KNOWS"

null

{"start":{"name":"Tom Burton"},"end":{"name":"John William"},"properties":{"time":"12:50:35.556000000+01:00","since":2016}}

null

如果我们想要指向远程 target 实例中存在的 secondDestDb 数据库,我们可以传递 boltConfig 参数,向 apoc.bolt.load(url, query, params, <boltConfig>) 传递附加参数。在这种情况下,我们可以传递 databaseName,即

CALL apoc.diff.graphs("MATCH p = (start:Person)-[rel:KNOWS]->(end) RETURN start, rel, end", "MATCH p = (start)-[rel:KNOWS]->(end) RETURN start, rel, end", {boltConfig: {databaseName: "secondDestDb"}, dest: {target: {type: "URL", value: "bolt://neo4j:apoc@localhost:7687"}}})

如果数据集相同,结果与上述相同。

© . This site is unofficial and not affiliated with Neo4j, Inc.