跳到内容

Schema 初始化策略

除了提供 Groovy 代码给 JanusGraph 服务器来初始化 schema 或执行任何自定义逻辑之外,JanusGraph 还提供了在启动时执行自定义 schema 初始化策略的能力。这些策略旨在帮助用户更轻松地定义和维护他们的 schema,但它们不能替代通过直接使用 JanusGraphManagement 开发的自定义 schema 管理流程。

每次通过 JanusGraphFactoryConfiguredGraphFactory 启动 JanusGraph 实例时,都会在启动前执行 schema 初始化策略。可以通过 schema.init.strategy 配置参数选择 schema 初始化策略。默认选择 none,这意味着 schema 初始化过程被跳过。

参数 schema.init.schema-drop-before-startup 可用于配置在启动时删除 schema 和数据(在测试环境中可能很方便)。

JSON Schema Initialization

当在 schema.init.strategy 中选择 json 配置选项时,它会通过 JSON 格式的 schema 定义触发 schema 初始化,该定义可以通过文件或字符串提供。

此策略的配置在 schema.init.json 命名空间下提供。设置 JSON schema 初始化最简单的方法是将 JSON schema 文件路径提供给 schema.init.json.file 或直接将 JSON schema 插入到 schema.init.json.string 配置选项中。

JSON Schema Format

通过 JSON 定义的 schema 必须是 org.janusgraph.core.schema.json.definition.JsonSchemaDefinition 类的反序列化 JSON 版本,其中顶级对象元素将是以下内容

  • vertexLabels
  • edgeLabels
  • propertyKeys
  • compositeIndexes
  • vertexCentricEdgeIndexes
  • vertexCentricPropertyIndexes
  • mixedIndexes

每个值都是一个数组,表示顶点标签、边标签、属性键、复合索引、顶点中心边索引、顶点中心属性索引或混合索引的列表。

JSON 顶点标签定义

每个顶点标签对象包含以下键

  • label - string 数据类型。(必需
  • staticVertex - boolean 数据类型。
  • partition - boolean 数据类型。
  • ttl - number 数据类型。

JSON 边标签定义

每个边标签对象包含以下键

  • label - string 数据类型。(必需
  • multiplicity - string 数据类型。允许值:MULTI, SIMPLE, ONE2MANY, MANY2ONE, ONE2ONE
  • unidirected - boolean 数据类型。
  • ttl - number 数据类型。

JSON 属性键定义

每个属性键对象包含以下键

  • key - string 数据类型。(必需
  • className - string 数据类型。这必须是所选属性数据类型的完整类路径。例如,java.lang.String, java.lang.Long,org.janusgraph.core.attribute.Geoshape。(必需
  • cardinality - string 数据类型。允许值:SINGLE, LIST, SET
  • ttl - number 数据类型。

JSON 复合索引定义

每个复合索引对象包含以下键

  • name - string 数据类型。(必需
  • typeClass - string 数据类型。被索引元素数据类型的完整类路径。允许值:org.apache.tinkerpop.gremlin.structure.Vertex, org.apache.tinkerpop.gremlin.structure.Edge。(必需
  • indexOnly - string 数据类型。顶点或边标签。
  • unique - boolean 数据类型。
  • consistency - string 数据类型。允许值:DEFAULT, LOCK, FORK
  • keys - 一个对象数组,表示 org.janusgraph.core.schema.json.definition.index.JsonIndexedPropertyKeyDefinition(参见索引定义后的定义)。这些是索引键。(必需
  • inlinePropertyKeys - 要内联到复合索引中的属性键数组。目前仅支持顶点复合索引。有关此功能的更多信息,请参阅文档

JSON 混合索引定义

每个混合索引对象包含以下键

  • name - string 数据类型。(必需
  • typeClass - string 数据类型。被索引元素数据类型的完整类路径。允许值:org.apache.tinkerpop.gremlin.structure.Vertex, org.apache.tinkerpop.gremlin.structure.Edge。(必需
  • indexOnly - string 数据类型。顶点或边标签。
  • indexBackend - string 数据类型。索引后端配置的名称。(必需
  • keys - 一个对象数组,表示 org.janusgraph.core.schema.json.definition.index.JsonIndexedPropertyKeyDefinition(参见索引定义后的定义)。这些是索引键。(必需

JSON 顶点中心边索引定义

每个顶点中心边索引对象包含以下键

  • name - string 数据类型。(必需
  • propertyKeys - 字符串数组(每个值都是 string 数据类型)。这些是用于索引的边属性。(必需
  • order - string 数据类型。允许值:asc, desc
  • indexedEdgeLabel - string 数据类型。要索引的边标签。(必需
  • direction - string 数据类型。允许值:OUT, IN, BOTH

JSON 顶点中心属性索引定义

每个顶点中心属性索引对象包含以下键

  • name - string 数据类型。(必需
  • propertyKeys - 字符串数组(每个值都是 string 数据类型)。这些是用于索引的元属性。(必需
  • order - string 数据类型。允许值:asc, desc
  • indexedPropertyKey - string 数据类型。要索引的属性键。(必需

JSON 复合索引和混合索引中定义的属性键的定义 (keys)

作为复合索引或混合索引的 keys 表示的每个属性键对象包含以下键

  • propertyKey - string 数据类型。(必需
  • parameters - 一个对象数组,表示 org.janusgraph.core.schema.json.definition.JsonParameterDefinition。这些是可选参数,用于让索引了解属性键的其他配置。(参见下面的描述)

JSON 复合索引和混合索引中属性键定义的参数定义 (parameters)

每个参数都是一个配置,用于让底层索引后端更好地配置相关属性。每个这样的参数包含以下键

  • key - string 数据类型。(必需
  • value - string 数据类型。(必需
  • parser - string 数据类型。这必须是用于解析参数 value 的解析器的完整类路径或预定义的快捷方式。此解析器必须实现 org.janusgraph.core.schema.json.parser.JsonParameterParser 接口并具有无参数构造函数。如果未提供,则默认使用 string 解析器。

预定义的 parser 快捷方式

  • string - 不更改 value 并按原样使用(String 数据类型)。
  • enum - 将提供的字符串(定义为 <full class path>.<enum option>)替换为实际的枚举值。例如,如果 value 具有字符串 org.janusgraph.core.schema.Mapping.STRING,它将被替换为实际的 STRING 枚举,并且不会被视为字符串。
  • boolean - 将值解析为 Boolean
  • byte - 将值解析为 Byte
  • short - 将值解析为 Short
  • integer - 将值解析为 Integer
  • long - 将值解析为 Long
  • float - 将值解析为 Float
  • double - 将值解析为 Double

参数可能包含定义为 ParameterType.customParameterName("<your custom key>")自定义键。为了在 JSON 中定义此类键,需要为 key 使用特定的前缀 - `%`custom%`(总共前缀由 10 个字符组成。如果某些字符在此处未正确呈现,您可以随时参考 org.janusgraph.graphdb.types.ParameterType.CUSTOM_PARAMETER_PREFIX 以查找这 10 个前缀字符)。因此,要定义像 similarity 这样的自定义键,您应该将键写为:%`custom%`similarity

JSON Schema 定义示例

遵循上述规则(在 JSON Schema Format 中定义),JSON schema 定义示例如下所示。

注意

以下 schema 有效且已使用 Cassandra 和 ElasticSearch 进行测试。它使用了一些与最终一致数据库和特别是 ElasticSearch 相关的参数。因此,某些特定于数据库的 schema 定义可能无法与其他数据库正常工作(如 similaritystring-analyzer)。下面的 schema 仅用于演示目的。

{
    "vertexLabels": [
        {
            "label": "normalVertex"
        },
        {
            "label": "partitionedVertex",
            "partition": true
        },
        {
            "label": "unmodifiableVertex",
            "staticVertex": true
        },
        {
            "label": "temporaryVertexForTwoHours",
            "staticVertex": true,
            "ttl": 7200000
        }
    ],
    "edgeLabels": [
        {
            "label": "normalSimpleEdge",
            "multiplicity": "SIMPLE",
            "unidirected": false
        },
        {
            "label": "unidirectedMultiEdge",
            "multiplicity": "MULTI",
            "unidirected": true
        },
        {
            "label": "temporaryEdgeForOneHour",
            "ttl": 3600000
        },
        {
            "label": "edgeWhichUsesLocksInEventualConsistentDBs",
            "consistency": "LOCK"
        },
        {
            "label": "edgeWhichUsesForkingInEventualConsistentDBs",
            "consistency": "FORK"
        }
    ],
    "propertyKeys": [
        {
            "key": "normalProperty",
            "className": "java.lang.Long"
        },
        {
            "key": "stringProperty",
            "className": "java.lang.String",
            "cardinality": "SINGLE"
        },
        {
            "key": "anotherStringProperty",
            "className": "java.lang.String",
            "cardinality": "SINGLE"
        },
        {
            "key": "listProperty",
            "className": "java.lang.Long",
            "cardinality": "LIST"
        },
        {
            "key": "geoshapeProperty",
            "className": "org.janusgraph.core.attribute.Geoshape"
        },
        {
            "key": "setProperty",
            "className": "java.lang.String",
            "cardinality": "SET"
        },
        {
            "key": "propertyWhichUsesLocksInEventualConsistentDBs",
            "className": "java.lang.Long",
            "cardinality": "SET",
            "consistency": "LOCK"
        },
        {
            "key": "temporaryPropertyForOneHour",
            "className": "java.lang.Long",
            "ttl": 3600000
        }
    ],
    "compositeIndexes": [
        {
            "name": "simpleCompositeIndex",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Vertex",
            "keys": [
                {
                    "propertyKey": "normalProperty"
                }
            ]
        },
        {
            "name": "indexOnlyForNormalVerticesOnListProperty",
            "indexOnly": "normalVertex",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Vertex",
            "keys": [
                {
                    "propertyKey": "listProperty"
                }
            ]
        },
        {
            "name": "compositeIndexOnEdge",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Edge",
            "keys": [
                {
                    "propertyKey": "normalProperty"
                }
            ]
        },
        {
            "name": "uniqueCompositeIndexWithLocking",
            "indexOnly": "unmodifiableVertex",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Vertex",
            "unique": true,
            "consistency": "LOCK",
            "keys": [
                {
                    "propertyKey": "stringProperty"
                }
            ]
        },
        {
            "name": "multiKeysCompositeIndex",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Vertex",
            "keys": [
                {
                    "propertyKey": "normalProperty"
                },
                {
                    "propertyKey": "anotherStringProperty"
                }
            ]
        },
        {
            "name": "compositeIndexWithInlinedProperties",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Vertex",
            "keys": [
                {
                    "propertyKey": "setProperty"
                }
            ],
            "inlinePropertyKeys": ["normalProperty", "stringProperty", "anotherStringProperty"]
        }
    ],
    "vertexCentricEdgeIndexes": [
        {
            "name": "vertexCentricBothDirectionsEdgeIndex",
            "indexedEdgeLabel": "normalSimpleEdge",
            "direction": "BOTH",
            "propertyKeys": [
                "normalProperty"
            ],
            "order": "asc"
        },
        {
            "name": "vertexCentricUnidirectedEdgeIndexOnMultipleProperties",
            "indexedEdgeLabel": "unidirectedMultiEdge",
            "direction": "OUT",
            "propertyKeys": [
                "stringProperty",
                "anotherStringProperty"
            ],
            "order": "desc"
        }
    ],
    "vertexCentricPropertyIndexes": [
        {
            "name": "normalVertexCentricPropertyKey",
            "indexedPropertyKey": "listProperty",
            "propertyKeys": [
                "normalProperty"
            ],
            "order": "asc"
        }
    ],
    "mixedIndexes": [
        {
            "name": "simpleMixedIndexOnMultipleProperties",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Vertex",
            "indexBackend": "search",
            "keys": [
                {
                    "propertyKey": "normalProperty"
                },
                {
                    "propertyKey": "geoshapeProperty"
                }
            ]
        },
        {
            "name": "mixedIndexWithParametersOnProperties",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Vertex",
            "indexBackend": "search",
            "keys": [
                {
                    "propertyKey": "stringProperty",
                    "parameters": [
                        {
                            "key": "string-analyzer",
                            "value": "standard",
                            "parser": "string"
                        },
                        {
                            "key": "mapping",
                            "value": "org.janusgraph.core.schema.Mapping.STRING",
                            "parser": "enum"
                        }
                    ]
                }
            ]
        },
        {
            "name": "mixedIndexWithCustomParameterKeyAndParserFullClassPath",
            "indexOnly": "unidirectedMultiEdge",
            "typeClass": "org.apache.tinkerpop.gremlin.structure.Edge",
            "indexBackend": "search",
            "keys": [
                {
                    "propertyKey": "anotherStringProperty",
                    "parameters": [
                        {
                            "key": "%`custom%`similarity",
                            "value": "boolean",
                            "parser": "string"
                        },
                        {
                            "key": "mapping",
                            "value": "org.janusgraph.core.schema.Mapping.TEXTSTRING",
                            "parser": "org.janusgraph.core.schema.json.parser.EnumJsonParameterParser"
                        }
                    ]
                }
            ]
        }
    ]
}

JSON Schema 初始化流程

目前,JSON schema 初始化流程很简单,不包括任何 schema 更新或 schema 迁移功能。流程分为多个阶段

  1. 创建简单元素:PropertyKeyVertexLabelEdgeLabel
  2. 创建索引:复合索引、顶点中心边索引、顶点中心属性索引、混合索引。
  3. 索引激活阶段(通过 schema.init.json.indices-activation 配置)。

注意

JSON schema 导入器的当前实现只创建元素,但即使您更改属性、边、顶点或索引的定义,它也从不更新它们。如果存在具有此类名称的元素,schema 导入器将跳过它而不对元素进行任何更新。此外,它从不从图中删除任何现有的 schema 元素。对于 schema 迁移和删除过程,请直接使用 graph.openManagement()

由于集群中创建了僵尸 JanusGraph 实例而难以初始化 schema 的用户可以利用配置选项 schema.init.json.force-close-other-instances。此选项将自动关闭集群中的所有 JanusGraph 实例(包括活动实例)。

警告

当使用 schema.init.json.force-close-other-instances 时,JanusGraph 将强制关闭集群中的任何其他实例。但是,它们可能不知道这一点,并继续在集群中工作而没有收到任何 schema 更新。这可能导致脑裂问题并损坏当前数据。建议改用 graph.unique-instance-idgraph.replace-instance-if-exists 选项,以防止创建 JanusGraph 僵尸实例。

JSON Schema 定义 API

也可以手动触发 JSON schema 定义 API,而不是依赖启动 schema 初始化过程。JSON schema 初始化的所有帮助方法都位于 org.janusgraph.core.schema.JsonSchemaInitStrategy 中。

// Schema from file
JsonSchemaInitStrategy.initializeSchemaFromFile(graph, "/path/to/schema.json")

// Schema from string
JsonSchemaInitStrategy.initializeSchemaFromString(graph, "{ \"vertexLabels\": [ { \"label\": \"my_vertex\" } ] }")

此外,还有额外的 initializeSchemaFromFileinitializeSchemaFromString 方法,可以在其中直接提供所有配置选项,而不是从图的配置中获取它们

  • initializeSchemaFromFile(JanusGraph graph, boolean createSchemaElements, boolean createSchemaIndices, IndicesActivationType indicesActivationType, boolean forceRollBackActiveTransactions, boolean forceCloseOtherInstances, long indexStatusTimeout, String jsonSchemaFilePath)
  • initializeSchemaFromString(JanusGraph graph, boolean createSchemaElements, boolean createSchemaIndices, IndicesActivationType indicesActivationType, boolean forceRollBackActiveTransactions, boolean forceCloseOtherInstances, long indexStatusTimeout, String jsonSchemaString)