elementIds 和 key 属性的作用

Neo4j 在内部通过其 elementId 识别节点和关系。 尽管这些内部标识符始终是生成的更改事件的一部分,但它们不安全,无法跟踪超出单个事务范围的数据。 因此,您应该以 节点键约束关系键约束 的形式为您的图实体定义逻辑/业务键。 具有节点和关系键约束的属性始终作为顶级对象包含在更改事件中。

如果在图实体上定义了key 约束,则所有参与的属性值都将作为节点更改和关系更改上的 event.keys 字段捕获。 此外,关系更改还包括关系的 startend 节点的相应参与键属性值。

如果在捕获更改事件后添加节点或关系键约束,则以前捕获的更改事件不会以追溯方式更新键信息。 从创建相应的约束的那一刻起,键属性就会被捕获。

节点键

假设以下约束对 PersonEmployee 标签生效。

Person 标签的节点键约束
CREATE CONSTRAINT person_names_key IF NOT EXISTS FOR (n:Person) REQUIRE (n.firstName, n.lastName) IS NODE KEY;
CREATE CONSTRAINT person_ssn_key IF NOT EXISTS FOR (n:Person) REQUIRE (n.ssn) IS NODE KEY;
Employee 标签的节点键约束
CREATE CONSTRAINT employee_key IF NOT EXISTS FOR (n:Employee) REQUIRE (n.id) IS NODE KEY

每当在具有 Person 标签的节点上发生更改时,并且 firstNamelastNamessn 属性分别设置为 johndoeX123456,则更改事件将包含以下键信息。

{
  //...
  "event": {
    "keys": {
      "Person": [
        {
          "firstName": "john",
          "lastName": "doe"
        },
        {
          "ssn": "X123456"
        }
      ]
    }
  }
  //...
}

同样,每当在具有 Employee 标签的节点上发生更改时,并且 id 属性设置为 1001,则更改事件将包含以下键信息。

{
  //...
  "event": {
    "keys": {
      "Employee": [
        {
          "id": 1001
        }
      ]
    }
  }
  //...
}

另一方面,如果更改的节点同时具有 PersonEmployee 标签,并且 firstNamelastNamessnid 属性分别设置为 johndoeY6543211001,则更改事件将包含以下键信息。

{
  //...
  "event": {
    "keys": {
      "Person": [
        {
          "firstName": "john",
          "lastName": "doe"
        },
        {
          "ssn": "Y654321"
        }
      ],
      "Employee": [
        {
          "id": 1001
        }
      ]
    }
  }
  //...
}

有关更改记录模式的完整描述,请参阅 更改事件的格式

尽管指定节点键属性的首选方法是创建节点键约束,但也可以使用同一组属性上的唯一节点属性节点属性存在约束来实现相同的效果。
对于 CDC,约束的创建方式无关紧要。

CREATE CONSTRAINT person_firstName_exists IF NOT EXISTS FOR (n:Person) REQUIRE n.firstName IS NOT NULL;
CREATE CONSTRAINT person_lastName_exists IF NOT EXISTS FOR (n:Person) REQUIRE n.lastName IS NOT NULL;
CREATE CONSTRAINT person_unique IF NOT EXISTS FOR (n:Person) REQUIRE (n.firstName, n.lastName) IS UNIQUE;

有关约束和相关命令语法的详细信息,请参阅 Cypher 手册 → 约束

关系键

假设以下约束对 MARRIED_TO 关系类型生效。

MARRIED_TO 类型的关系键
CREATE CONSTRAINT married_to_register_key IF NOT EXISTS FOR ()-[r:MARRIED_TO]-() REQUIRE (r.registerId) IS RELATIONSHIP KEY;
CREATE CONSTRAINT married_to_official_key IF NOT EXISTS FOR ()-[r:MARRIED_TO]-() REQUIRE (r.official) IS RELATIONSHIP KEY;

每当在类型为 MARRIED_TO 的关系上发生更改时,并且 registerIdofficial 属性分别设置为 1125Alice Roberts,则更改事件将包含以下键信息。

{
  //...
  "event": {
    "keys": [
      {
        "registerId": 1125
      },
      {
        "official": "Alice Roberts"
      }
    ]
  }
  //...
}

如果关系的起始节点和结束节点对应于具有节点键约束的节点,则这些属性值也将包含在更改事件中。

{
  //...
  "event": {
    "start": {
      "elementId": "<element-id>",
      "labels": ["Person"],
      "keys": {
        "Person": [
          {
            "firstName": "john",
            "lastName": "doe"
          }
        ]
      }
    },
    "end": {
      "elementId": "<element-id>",
      "labels": ["Person"],
      "keys": {
        "Person": [
          {
            "firstName": "mary",
            "lastName": "doe"
          }
        ]
      }
    },
    "keys": [
      {
        "registerId": 1125
      },
      {
        "official": "Alice Roberts"
      }
    ]
  }
  //...
}

有关更改记录模式的完整描述,请参阅 更改事件的格式

尽管指定关系键属性的首选方法是创建关系键约束,但也可以使用同一组属性上的唯一关系属性关系属性存在约束来实现相同的效果。
对于更改数据捕获,约束的创建方式无关紧要。

CREATE CONSTRAINT married_to_registerId_exists IF NOT EXISTS FOR ()-[r:MARRIED_TO]-() REQUIRE (r.registerId) IS NOT NULL;
CREATE CONSTRAINT married_to_registerId_unique IF NOT EXISTS FOR ()-[r:MARRIED_TO]-() REQUIRE (r.registerId) IS UNIQUE;

有关约束和相关命令语法的详细信息,请参阅 Cypher 手册 → 约束