模式优化
|
本页中的所有示例均假设 |
虽然 Neo4j 不强制要求使用模式(Schema),但在写入数据之前添加索引和约束可以提高写入过程的效率。在更新节点或关系时,应用约束也是避免重复数据的最佳方式。
下面总结了用于模式优化的连接器选项。
|
此处描述的模式优化选项不能与 |
| 选项 | 描述 | 值 | 默认 |
|---|---|---|---|
|
使用 (已弃用,建议改用 |
|
|
|
|
|
|
|
|
|
|
|
在节点和关系上创建 属性类型和属性存在性 约束,强制执行 DataFrame 模式中的类型和非空性约束。 |
逗号分隔的 |
|
节点属性索引已弃用
Neo4j 中的 索引 通常用于提高搜索性能。
您可以通过将 schema.optimization.type 选项设置为 INDEX 来创建索引。
val df = List(
"Product 1",
"Product 2",
).toDF("name")
df.write
.format("org.neo4j.spark.DataSource")
.mode(SaveMode.Overwrite)
.option("labels", ":Product")
.option("node.keys", "name")
.option("schema.optimization.type", "INDEX")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询
CREATE INDEX spark_INDEX_Product_name FOR (n:Product) ON (n.name)
索引名称的格式为 spark_INDEX_<LABEL>_<NODE_KEYS>,其中 <LABEL> 是来自 labels 选项的第一个标签,<NODE_KEYS> 是 node.keys 选项中指定的一个或多个属性的短横线分隔序列。
说明
-
如果索引已存在,则不会重新创建。
-
对于多个标签,仅使用第一个标签来创建索引。
节点属性唯一性约束
节点属性唯一性约束 确保具有特定标签的所有节点的属性值都是唯一的。对于多个属性的唯一性约束,属性值的组合必须是唯一的。
您可以通过将 schema.optimization.node.keys 选项设置为 UNIQUE 来创建约束。
val df = List(
"Product 1",
"Product 2",
).toDF("name")
df.write
.format("org.neo4j.spark.DataSource")
.mode(SaveMode.Overwrite)
.option("labels", ":Product")
.option("node.keys", "name")
.option("schema.optimization.node.keys", "UNIQUE")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询
CREATE CONSTRAINT `spark_NODE_UNIQUE-CONSTRAINT_Product_name` IF NOT EXISTS FOR (e:Product) REQUIRE (e.name) IS UNIQUE
说明
-
如果约束已存在,则不会重新创建。
-
对于多个标签,仅使用第一个标签来创建索引。
-
如果同一个属性上已经存在键约束,则无法在该节点属性上创建唯一性约束。
-
此模式优化仅适用于
Overwrite保存模式。
|
在 5.3.0 版本之前,可以通过将 |
节点键约束
节点键约束 确保对于给定的节点标签和属性集:
-
所有属性在具有该标签的所有节点上都存在。
-
属性值的组合是唯一的。
您可以通过将 schema.optimization.node.keys 选项设置为 KEY 来创建约束。
val df = List(
"Product 1",
"Product 2",
).toDF("name")
df.write
.format("org.neo4j.spark.DataSource")
.mode(SaveMode.Overwrite)
.option("labels", ":Product")
.option("node.keys", "name")
.option("schema.optimization.node.keys", "KEY")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询
CREATE CONSTRAINT `spark_NODE_KEY-CONSTRAINT_Product_name` IF NOT EXISTS FOR (e:Product) REQUIRE (e.name) IS NODE KEY
说明
-
如果约束已存在,则不会重新创建。
-
如果同一个属性上已经存在唯一性约束,则无法在该节点属性上创建键约束。
-
此模式优化仅适用于
Overwrite保存模式。
关系属性唯一性约束
关系属性唯一性约束 确保具有特定类型的所有关系的属性值都是唯一的。对于多个属性的唯一性约束,属性值的组合必须是唯一的。
您可以通过将 schema.optimization.relationship.keys 选项设置为 UNIQUE 来创建约束。
val df = Seq(
("John", "Doe", 1, "Product 1", 200, "ABC100"),
("Jane", "Doe", 2, "Product 2", 100, "ABC200")
).toDF("name", "surname", "customerID", "product", "quantity", "order")
df.write
.mode(SaveMode.Overwrite)
.format("org.neo4j.spark.DataSource")
.option("relationship", "BOUGHT")
.option("relationship.save.strategy", "keys")
.option("relationship.source.save.mode", "Overwrite")
.option("relationship.source.labels", ":Customer")
.option("relationship.source.node.properties", "name,surname,customerID:id")
.option("relationship.source.node.keys", "customerID:id")
.option("relationship.target.save.mode", "Overwrite")
.option("relationship.target.labels", ":Product")
.option("relationship.target.node.properties", "product:name")
.option("relationship.target.node.keys", "product:name")
.option("relationship.properties", "quantity,order")
.option("schema.optimization.relationship.keys", "UNIQUE")
.option("relationship.keys", "order")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询
CREATE CONSTRAINT `spark_RELATIONSHIP_UNIQUE-CONSTRAINT_BOUGHT_order` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE (e.order) IS UNIQUE
说明
-
如果约束已存在,则不会重新创建。
-
如果同一个属性上已经存在键约束,则无法在该关系属性上创建唯一性约束。
-
此模式优化仅适用于
Overwrite保存模式。
关系键约束
关系键约束 确保对于给定的关系类型和属性集:
-
所有属性在具有该类型的所有关系上都存在。
-
属性值的组合是唯一的。
您可以通过将 schema.optimization.relationship.keys 选项设置为 KEY 来创建约束。
val df = Seq(
("John", "Doe", 1, "Product 1", 200, "ABC100"),
("Jane", "Doe", 2, "Product 2", 100, "ABC200")
).toDF("name", "surname", "customerID", "product", "quantity", "order")
df.write
.mode(SaveMode.Overwrite)
.format("org.neo4j.spark.DataSource")
.option("relationship", "BOUGHT")
.option("relationship.save.strategy", "keys")
.option("relationship.source.save.mode", "Overwrite")
.option("relationship.source.labels", ":Customer")
.option("relationship.source.node.properties", "name,surname,customerID:id")
.option("relationship.source.node.keys", "customerID:id")
.option("relationship.target.save.mode", "Overwrite")
.option("relationship.target.labels", ":Product")
.option("relationship.target.node.properties", "product:name")
.option("relationship.target.node.keys", "product:name")
.option("relationship.properties", "quantity,order")
.option("schema.optimization.relationship.keys", "KEY")
.option("relationship.keys", "order")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询
CREATE CONSTRAINT `spark_RELATIONSHIP_KEY-CONSTRAINT_BOUGHT_order` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE (e.order) IS RELATIONSHIP KEY
说明
-
如果约束已存在,则不会重新创建。
-
如果同一个属性上已经存在唯一性约束,则无法在该关系属性上创建键约束。
-
此模式优化仅适用于
Overwrite保存模式。
属性类型和属性存在性约束
连接器使用 DataFrame 模式来强制执行类型(使用 数据类型映射 中描述的映射),并使用每列的 nullable 标志来决定是否强制执行存在性。
您可以创建:
-
通过将
schema.optimization选项设置为TYPE,为节点和关系创建属性类型约束。 -
通过将
schema.optimization选项设置为EXISTS,为节点和关系创建属性存在性约束。 -
通过将
schema.optimization选项设置为TYPE,EXISTS,同时创建两者。
说明
-
如果约束已存在,则不会重新创建。
在节点上
示例
df.write
.format("org.neo4j.spark.DataSource")
.mode(SaveMode.Overwrite)
.option("labels", ":Person")
.option("node.keys", "surname")
.option("schema.optimization", "TYPE,EXISTS")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询(每列 DataFrame 列运行一个查询)
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-name` IF NOT EXISTS FOR (e:Person) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-surname` IF NOT EXISTS FOR (e:Person) REQUIRE e.surname IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-age` IF NOT EXISTS FOR (e:Person) REQUIRE e.age IS :: INTEGER
如果 DataFrame 列不可为空,连接器将运行额外的模式查询。例如,如果 age 列不可为空,连接器将运行以下模式查询
CREATE CONSTRAINT `spark_NODE-NOT_NULL-CONSTRAINT-Person-age` IF NOT EXISTS FOR (e:Person) REQUIRE e.age IS NOT NULL
df.write
.format("org.neo4j.spark.DataSource")
.mode(SaveMode.Overwrite)
.option("labels", ":Person")
.option("node.keys", "surname")
.option("schema.optimization", "TYPE,EXISTS")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询(每列 DataFrame 列运行一个查询)
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-name` IF NOT EXISTS FOR (e:Person) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-surname` IF NOT EXISTS FOR (e:Person) REQUIRE e.surname IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-age` IF NOT EXISTS FOR (e:Person) REQUIRE e.age IS :: INTEGER
如果 DataFrame 列不可为空,连接器将运行额外的模式查询。例如,如果 age 列不可为空,连接器将运行以下模式查询
CREATE CONSTRAINT `spark_NODE-NOT_NULL-CONSTRAINT-Person-age` IF NOT EXISTS FOR (e:Person) REQUIRE e.age IS NOT NULL
在写入过程开始之前,连接器会运行以下模式查询(每列 DataFrame 列运行一个查询)
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-name` IF NOT EXISTS FOR (e:Person) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-surname` IF NOT EXISTS FOR (e:Person) REQUIRE e.surname IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Person-age` IF NOT EXISTS FOR (e:Person) REQUIRE e.age IS :: INTEGER
如果 DataFrame 列不可为空,连接器将运行额外的模式查询。例如,如果 age 列不可为空,连接器将运行以下模式查询
CREATE CONSTRAINT `spark_NODE-NOT_NULL-CONSTRAINT-Person-age` IF NOT EXISTS FOR (e:Person) REQUIRE e.age IS NOT NULL
在关系上
示例
val df = Seq(
("John", "Doe", 1, "Product 1", 200, "ABC100"),
("Jane", "Doe", 2, "Product 2", 100, "ABC200")
).toDF("name", "surname", "customerID", "product", "quantity", "order")
df.write
.mode(SaveMode.Overwrite)
.format("org.neo4j.spark.DataSource")
.option("relationship", "BOUGHT")
.option("relationship.save.strategy", "keys")
.option("relationship.source.save.mode", "Overwrite")
.option("relationship.source.labels", ":Customer")
.option("relationship.source.node.properties", "name,surname,customerID:id")
.option("relationship.source.node.keys", "customerID:id")
.option("relationship.target.save.mode", "Overwrite")
.option("relationship.target.labels", ":Product")
.option("relationship.target.node.properties", "product:name")
.option("relationship.target.node.keys", "product:name")
.option("relationship.properties", "quantity,order")
.option("schema.optimization", "TYPE,EXISTS")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询(先是源节点和目标节点属性的属性类型约束查询,然后是代表关系属性的每列 DataFrame 列的属性类型约束查询)
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-name` IF NOT EXISTS FOR (e:Customer) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-surname` IF NOT EXISTS FOR (e:Customer) REQUIRE e.surname IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-id` IF NOT EXISTS FOR (e:Customer) REQUIRE e.id IS :: INTEGER
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Product-name` IF NOT EXISTS FOR (e:Product) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_RELATIONSHIP-TYPE-CONSTRAINT-BOUGHT-quantity` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.quantity IS :: INTEGER
CREATE CONSTRAINT `spark_RELATIONSHIP-TYPE-CONSTRAINT-BOUGHT-order` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.order IS :: STRING
如果 DataFrame 列不可为空,连接器将运行额外的模式查询。例如,如果 experience 列不可为空,连接器将运行以下模式查询
CREATE CONSTRAINT `spark_NODE-NOT_NULL-CONSTRAINT-Customer-id` IF NOT EXISTS FOR (e:Customer) REQUIRE e.id IS NOT NULL
CREATE CONSTRAINT `spark_RELATIONSHIP-NOT_NULL-CONSTRAINT-BOUGHT-quantity` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.quantity IS NOT NULL
val df = Seq(
("John", "Doe", 1, "Product 1", 200, "ABC100"),
("Jane", "Doe", 2, "Product 2", 100, "ABC200")
).toDF("name", "surname", "customerID", "product", "quantity", "order")
df.write
.mode(SaveMode.Overwrite)
.format("org.neo4j.spark.DataSource")
.option("relationship", "BOUGHT")
.option("relationship.save.strategy", "keys")
.option("relationship.source.save.mode", "Overwrite")
.option("relationship.source.labels", ":Customer")
.option("relationship.source.node.properties", "name,surname,customerID:id")
.option("relationship.source.node.keys", "customerID:id")
.option("relationship.target.save.mode", "Overwrite")
.option("relationship.target.labels", ":Product")
.option("relationship.target.node.properties", "product:name")
.option("relationship.target.node.keys", "product:name")
.option("relationship.properties", "quantity,order")
.option("schema.optimization", "TYPE,EXISTS")
.save()
模式查询
在写入过程开始之前,连接器会运行以下模式查询(先是源节点和目标节点属性的属性类型约束查询,然后是代表关系属性的每列 DataFrame 列的属性类型约束查询)
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-name` IF NOT EXISTS FOR (e:Customer) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-surname` IF NOT EXISTS FOR (e:Customer) REQUIRE e.surname IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-id` IF NOT EXISTS FOR (e:Customer) REQUIRE e.id IS :: INTEGER
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Product-name` IF NOT EXISTS FOR (e:Product) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_RELATIONSHIP-TYPE-CONSTRAINT-BOUGHT-quantity` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.quantity IS :: INTEGER
CREATE CONSTRAINT `spark_RELATIONSHIP-TYPE-CONSTRAINT-BOUGHT-order` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.order IS :: STRING
如果 DataFrame 列不可为空,连接器将运行额外的模式查询。例如,如果 experience 列不可为空,连接器将运行以下模式查询
CREATE CONSTRAINT `spark_NODE-NOT_NULL-CONSTRAINT-Customer-id` IF NOT EXISTS FOR (e:Customer) REQUIRE e.id IS NOT NULL
CREATE CONSTRAINT `spark_RELATIONSHIP-NOT_NULL-CONSTRAINT-BOUGHT-quantity` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.quantity IS NOT NULL
在写入过程开始之前,连接器会运行以下模式查询(先是源节点和目标节点属性的属性类型约束查询,然后是代表关系属性的每列 DataFrame 列的属性类型约束查询)
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-name` IF NOT EXISTS FOR (e:Customer) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-surname` IF NOT EXISTS FOR (e:Customer) REQUIRE e.surname IS :: STRING
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Customer-id` IF NOT EXISTS FOR (e:Customer) REQUIRE e.id IS :: INTEGER
CREATE CONSTRAINT `spark_NODE-TYPE-CONSTRAINT-Product-name` IF NOT EXISTS FOR (e:Product) REQUIRE e.name IS :: STRING
CREATE CONSTRAINT `spark_RELATIONSHIP-TYPE-CONSTRAINT-BOUGHT-quantity` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.quantity IS :: INTEGER
CREATE CONSTRAINT `spark_RELATIONSHIP-TYPE-CONSTRAINT-BOUGHT-order` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.order IS :: STRING
如果 DataFrame 列不可为空,连接器将运行额外的模式查询。例如,如果 experience 列不可为空,连接器将运行以下模式查询
CREATE CONSTRAINT `spark_NODE-NOT_NULL-CONSTRAINT-Customer-id` IF NOT EXISTS FOR (e:Customer) REQUIRE e.id IS NOT NULL
CREATE CONSTRAINT `spark_RELATIONSHIP-NOT_NULL-CONSTRAINT-BOUGHT-quantity` IF NOT EXISTS FOR ()-[e:BOUGHT]->() REQUIRE e.quantity IS NOT NULL