专栏首页咻咻ing5. Schema和数据类型

5. Schema和数据类型

JanusGraph图是通过Schema定义,每个Schema包含边标签、属性、点标签。JanusGraph的Schema可以被显式或者隐式定义。 建议开发者在程序开发期间显式的定义图的Schema。显式的定义Schema可以提高程序的健壮性,也能够方便与同事的协作开发。注意,JanusGraph的Schema可以随着时间的推移而改变,而不会中断正常的数据库操作。扩展Schema不会减慢查询速度,也不需要数据库停机。

Schema第一次被创建时,需要指定他们的类型例如边的标签、属性的key、顶点的标签。无法更改特定元素的Schema类型。这是为了确保系统的稳定。

除了本节中介绍的Schema定义方式外,第30章高级教程中也讲了如何定义来提高性能。

1. 定义边的标签

连接两个顶点的每条边都有一个标签,用来描述他们之间的关系。例如:顶点A和顶点B之间具有朋友关系,那他们之间边的标签可以定义为friend。

要定义边的标签,通过graph实例或者management调用方法makeEdgeLabel(String),传入边标签的名称作为参数。边标签的名称必须是全局唯一的。这个方法返回一个边标签的builder,用来定义边的multiplicity。边标签的多重性定义了该标签在所有边上的多重约束,即顶点对之间的最大边数。 JanusGraph支持以下多重性设置。

1.1. 边标签的Multiplicity
  • MULTI: 允许任意一对顶点之间的同一标签有多条边。换句话说,该图是关于这种边标签的多图。边的多样性没有约束。
  • SIMPLE: 在任何一对顶点之间最多允许此类标签的一条边。换句话说,该图是关于该标签的单图。保证该标签的边在任意两个顶点之间是唯一的。
  • MANY2ONE: 在图中的任何顶点上最多允许此标签的一条出边,但不对入边施加约束。边标签mother是MANY2ONE多样性的一个例子,因为每个人最多只有一个母亲,但母亲可以有多个孩子。
  • ONE2MANY: 在图中的任何顶点上最多允许此标签的一条入边,但不对出边施加约束。边标签winnerOf是具有ONE2MANY多样性的示例,因为每个比赛最多只能赢得一个人,但是一个人可以赢得多个比赛。
  • ONE2ONE: 在图的任何顶点上最多允许此标签的一个入边和一个出边。边标签marriedTo是ONE2ONE多样性的一个例子,因为一个人与另一个人结婚。

默认的Multiplicity是MULTI。 边标签的定义是通过调用构建器上的make()方法完成的,该方法返回的是定义的边标签,如下例所示。

mgmt = graph.openManagement()
follow = mgmt.makeEdgeLabel('follow').multiplicity(MULTI).make()
mother = mgmt.makeEdgeLabel('mother').multiplicity(MANY2ONE).make()
mgmt.commit()

2. 定义属性

顶点和边的属性是键值对。 例如,属性name ='Daniel'具有键名和值'Daniel'。 属性键是JanusGraph架构的一部分,可以约束允许的数据类型和值的基数。

要定义属性键,请在打开的图形或管理事务上调用makePropertyKey(String),并提供属性键的名称作为参数。 属性键名称在图形中必须是唯一的,建议避免使用属性名称中的空格或特殊字符。 此方法返回属性键的构建器。

2.1. 属性的数据类型

使用dataType(Class)定义属性的数据类型。 JanusGraph将使用已经定义的数据类型给属性赋值,来保证添加到图中的数据有效。 例如,可以定义属性name的数据类型是String。

允许把任何(可序列化的)的值赋值给数据类型为Object.class的属性。 但是,建议尽可能的使用具体的数据类型。 设置的数据类型必须是具体的类,而不能是接口或抽象类。 JanusGraph确保类相等,因此不允许添加已设置数据类型的子类。

JanusGraph支持以下数据类型。

类型

描述

String

Character

Boolean

Byte

Short

Integer

Long

Float

Double

Date

Geoshape

UUID

2.2. 属性的Cardinality

使用Cardinality来定义顶点上相关属性的Cardinality。

  • SINGLE:对于这个值,每个属性最多允许一个值。 换句话说,这个键→值对在图中的所有顶点中都是唯一的。 属性birthDate是具有SINGLE基数的例子,因为每个人只有一个出生日期。
  • LIST:允许每个顶点的这个属性有任意多个值。 换句话说,这个属性的值是一个list列表。 假设我们将传感器作为图中的顶点,则属性sensorReading是一个具有LIST基数的例子,需要记录大量的传感器数据。
  • SET:允许多个值,但每个顶点的此属性值不能重复。 换句话说,此属性与一组值相关联。 如果我们想要记录一个人的所有姓名(包括昵称,婚前姓名等),则属性name具有SET基数。

默认的cardinality值为SINGLE。 注意,边的属性和属性的cardinality是SINGLE。 不支持为边或属性上的单个key赋多个值。

mgmt = graph.openManagement()
birthDate = mgmt.makePropertyKey('birthDate').dataType(Long.class).cardinality(Cardinality.SINGLE).make()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(Cardinality.SET).make()
sensorReading = mgmt.makePropertyKey('sensorReading').dataType(Double.class).cardinality(Cardinality.LIST).make()
mgmt.commit()

3. 关系类型

边的标签和属性共同称为关系类型。 关系类型的名称在图中必须是唯一的,这意味着属性和边标签不能具有相同的名称。 JanusGraph API中有一些方法可以查询或检验关系类型中是否包含属性和边标签。

mgmt = graph.openManagement()
if (mgmt.containsRelationType('name'))
    name = mgmt.getPropertyKey('name')
mgmt.getRelationTypes(EdgeLabel.class)
mgmt.commit()

4. 定义顶点标签

像边一样,顶点也有标签。 与边标签不同,顶点标签是可选的。 顶点标签可用于区分不同类型的顶点,例如, 用户顶点和产品顶点。

虽然标签在概念和数据模型上是可选的,但JanusGraph在内部实现中会为所有顶点分配一个标签。 addVertex方法创建顶点时使用JanusGraph的默认标签。

要创建标签,请调用方法makeVertexLabel(String).make(),并提供顶点标签的name作为参数。 顶点标签的名称在图中必须是唯一的。

mgmt = graph.openManagement()
person = mgmt.makeVertexLabel('person').make()
mgmt.commit()
// Create a labeled vertex
person = graph.addVertex(label, 'person')
// Create an unlabeled vertex
v = graph.addVertex()
graph.tx().commit()

5. 自动创建Schema

如果未明确定义边标签,属性或顶点标签,则在边,顶点或属性首次使用时,它会被隐式定义。 JanusGraph默认的的DefaultSchemaMaker配置会定义这些类型。

默认情况下,隐式创建的边标签具有多重性MULTI,隐式创建的属性具有基数SINGLE和数据类型是Object.class。 用户可以通过实现和注册自己的DefaultSchemaMaker来控制Schema的自动创建方式。

强烈建议显示的定义所有的Schema并且通过在JanusGraph配置中设置schema.default = none来禁用自动创建Schema。

6. 更改Schema

边标签,属性键或顶点标签的定义一旦提交则无法更改。 但是,可以通过JanusGraphManagement.changeName(JanusGraphSchemaElement,String)来更改Schema中元素的名字,如以下示例所示,其中属性place被重命名为location。

mgmt = graph.openManagement()
place = mgmt.getPropertyKey('place')
mgmt.changeName(place, 'location')
mgmt.commit()

请注意,在正在运行的遍历查询和集群中的JanusGraph实例中,Schema名字的更改可能不会立即生效。虽然通过后端存储向所有JanusGraph实例通知了Schema名字更改,但它可能需要一段时间才能生效,并且如果遇到某些故障情况(如网络分区)可能需要重启实例。因此,用户必须确保满足以下任一条件:

  • 重命名的标签或key当前未使用(即写入或读取),并且在所有JanusGraph实例都知道name更改之前不会使用。
  • 执行的遍历主动适配短暂的中间状态,其中旧名称或新名称基于特定的JanusGraph实例和名称更改的状态。例如,这意味着遍历可能同时查询两个name。

如果需要重新定义现有的Schema类型,建议将此类型的名称更改为当前未使用并且永远不会使用的名称。之后,可以使用原来的name定义新标签或key,从而有效地替换旧标签或key。但注意,这不会影响使用先前的类型去写入顶点,边或属性。不支持在线重新定义现有图元素,必须通过图批量转换完成。

7. Schema约束

Schema的定义允许用户显式配置属性和连接约束。属性可以绑定到特定的顶点标签和/或边标签。此外,连接约束允许用户明确定义哪两个顶点标签被连接通过边缘标签。这些约束用于确保图与给定的模型匹配。例如,对于众神的图,god可以是另一个god的兄弟,而不是怪物,god可以拥有年龄属性,但位置不能具有年龄年龄。这些约束默认情况下是禁用的。

通过设置schema.constraints = true来启用这些schema约束。这个设置依赖schema.default配置。如果schema.default设置为none,则会因违反schema约束而抛出IllegalArgumentException。如果schema.default未设置为none,则会自动创建schema约束,而不会引发异常。激活schema约束对现有数据没有影响,因为这些schema约束仅在插入过程中应用。因此,这些约束完全不会影响数据的读取。

可以使用JanusGraphManagement.addProperties(VertexLabel,PropertyKey ...)将多个属性绑定到同一顶点,例如:

mgmt = graph.openManagement()
person = mgmt.makeVertexLabel('person').make()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(Cardinality.SET).make()
birthDate = mgmt.makePropertyKey('birthDate').dataType(Long.class).cardinality(Cardinality.SINGLE).make()
mgmt.addProperties(person, name, birthDate)
mgmt.commit()

可以使用JanusGraphManagement.addProperties(EdgeLabel,PropertyKey ...)将多个属性绑定到同一条边,例如:

mgmt = graph.openManagement()
follow = mgmt.makeEdgeLabel('follow').multiplicity(MULTI).make()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(Cardinality.SET).make()
mgmt.addProperties(follow, name)
mgmt.commit()

使用JanusGraphManagement.addConnection(EdgeLabel,VertexLabel out,VertexLabel in)定义边的出点和入点的连接,例如:

mgmt = graph.openManagement()
person = mgmt.makeVertexLabel('person').make()
company = mgmt.makeVertexLabel('company').make()
works = mgmt.makeEdgeLabel('works').multiplicity(MULTI).make()
mgmt.addConnection(works, person, company)
mgmt.commit()

本文分享自微信公众号 - 咻咻ing(gh_d9f867ad7230)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-04-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 8. 部署方案

    JanusGraph提供了多种存储和索引后端选项,可以灵活地部署它们。本章介绍了一些可能的部署方案,以帮助解决这种灵活性带来的复杂性。

    咻咻ing
  • Golang:一文解决Map并发问题

    在Go 1.6之前, 内置的map类型是部分goroutine安全的,并发的读没有问题,并发的写可能有问题。自go 1.6之后, 并发地读写map会报错,这在一...

    咻咻ing
  • 使用Gitee+Hexo搭建个人博客

    目前国内访问GitHub速度慢,还可能被墙,所以Gitee来构建个人博客。Gitee类似国内版的GitHub,访问速度有保证。

    咻咻ing
  • eeglab教程系列(1)-加载、显示数据

    在matlab中安装eeglab,请看安装教程:eeglab在MATLAB中安装教程

    脑机接口社区
  • eeglab中文教程系列(1)-加载、显示数据

    本教程为脑机学习者Rose发表于公众号:脑机接口社区(微信号:Brain_Computer)

    脑机接口社区
  • 如何使用Python中的字典解析

    列表解析,是Python中常用的操作,它语法简单,循环速度足够快。但是,你了解字典解析吗?它跟列表解析一样吗?

    老齐
  • hexo搭建github.io博客

    ### Quick Start #### 安装 node,git,注册好github账号 (网站有很多教程,安装方法这里就不详细展开了,注意:github账号用...

    前端迷
  • 谈谈服务器运营领域的机器学习

    本文我们来谈谈近几年机器学习在服务器运营领域的一些实践。

    TEG云端专业号
  • 19:救援

    19:救援 总时间限制: 1000ms 内存限制: 65536kB描述 救生船从大本营出发,营救若干屋顶上的人回到大本营,屋顶数目以及每个屋顶的坐标  和人数...

    attack
  • Android安全启动功能

    验证启动(安全启动)功能旨在保证设备软件(从硬件信任根直到系统分区)的完整性。在启动过程中,无论是在每个阶段,都会在进入下一个阶段之前先验证下一个阶段的完整性和...

    安智客

扫码关注云+社区

领取腾讯云代金券