JanusGraph的schema主要是由edge label(边),vertex label(顶点)和property key(属性的键)组成。edge label和vertex label可以拥有多个property。edge label的property的cardinality属性只能是SINGLE。
JanusGraph支持显式和隐式定义。官方建议显式定义schema,可以提供协同开发效率。edge label,vertex label,property一经定义是不能修改和删除的(但提供了修改名称的方法),主要是为了保证模型的稳定性。
一、定义Edge Label
Edge(边),定义两个顶点间的关系,edge label的名称在一个图中必须是唯一的。JanusGraph提供一个builder方法创建edge label,这个builder还提供了一个方法定义边的多重性(mulitiplicit)。边标签的多重性定义了该标签的所有边上的多重性约束,即顶点对之间的最大边数。
1. 边标签的多重性
MULIT: 允许多条相同标签的边在两个顶点之间,即多重图,边的多重性没有约束。
SIMPLE: 只允许给定的标签在顶点对之间是唯一的。
MANY2ONE:在一个图中,允许给定的标签在任意顶点上只有一条传出边(outgoing edge),而不对传入边(incoming edge)施加限制。举例,父子关系,儿子只有一个父亲,而父亲有多个儿子。
ONE2MANY:与MANY2ONE相反,允许给定的标签在任意顶点上只有一条传入边(incoming edge),而不对传出边(outgoing edge)施加限制。
ONE2ONE:允许给定的标签在任意顶点上只有一条传入边和一条传出边。女子"嫁给"男子,是一个典型的ONE2ONE关系。
2. 创建edge label代码示例
mgmt = graph.openManagement();
follow = mgmt.makeEdgeLabel('follow').multiplicity(MULTI).make();
mother = mgmt.makeEdgeLabel('mother').multiplicity(MANY2ONE).make();
mgmt.commit(); // 千万别漏这句
二、定义Property Keys
顶点和边的Property(属性)都是键值对模式。Property的键必须图中唯一的,键的定义不要包含空格和特殊字符。Property作为JanusGraph schema的一部分,允许约束它的数据类型和值得基数。
1. 支持的数据类型
Name | Description |
---|---|
String | Character sequence |
Character | Individual character |
Boolean | true or false |
Byte | byte value |
Short | short value |
Integer | integer value |
Long | long value |
Float | 4 byte floating point number |
Double | 8 byte floating point number |
Date | Specific instant in time (java.util.Date ) |
Geoshape | Geographic shape like point, circle or box |
UUID | Universally unique identifier (java.util.UUID ) |
2. 支持的值的基数(Cardinality)
SINGLE: 典型的键值对,key->value, 一个键指向一个值。
LIST: 一个键可以指向一组值且可值可重复。
SET: 一个键可以指向一组值,但值不可重复。
默认Property的Cardinality是SINGLE,边只允许SINGLE的Property,顶点没有限制。
3. 创建Property例子
mgmt = graph.openManagement()
birthDate = mgmt.makePropertyKey('birthDate').dataType(Long.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SET).make()
sensorReading = mgmt.makePropertyKey('sensorReading').dataType(Double.class).cardinality(org.janusgraph.core.Cardinality.LIST).make()
mgmt.commit()
三、定义Vertex Label
顶点标签是可选的,顶点标签用于区分不同的顶点类型,例如user vertex, product vertex。
虽然顶点标签是可选的,但是在调用addVertex()方法时,如果不制定label,会使用默认标签。顶点标签和边标签一样,都是图中唯一的。
1. 创建顶点标签示例
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() // 必须加上
四、自动Schema Maker
JanusGraph支持隐式标签,边标签的multiplicity默认是MULIT,Property的cardinality默认是SINGLE。如上文所讲,建议通过显示定义Schema,可以在配置中增加schema.default=none, 关闭隐式Schema,强制使用显示Schema定义。
五、修改Schema
上文已经说过,JanusGraph是不直接修改edge label, property key和vertex label的,但是可以修改这些元数据的名字。
mgmt = graph.openManagement()
place = mgmt.getPropertyKey('place')
mgmt.changeName(place, 'location')
mgmt.commit()
修改不会在整个集群中生效,需要一会让后端存储保存成功。这可能会引发一些问题甚至需要实例重启。所以,用户必须确保:
- 修改的标签或键名称不会立即使用,并且必须保证在所有实例都知道修改后才能使用。
- 正在运行的事务主动适应短暂的中间时段,在此期间,旧名称或新名称根据特定JanusGraph实例和名称更改通知的状态有效。例如,这可能意味着事务同时查询两个名称
如果要修改Schema,应该先把旧的名字改为一个不被使用的新名字,然后用原有的名字定义新的标签和键。但必须说明的是,这样的修改,对之前的数据不会发生变化。数据需要批量处理转换。
六、结构约束
可以显示的定义属性绑定顶点,也可以定义通过某一边标签将某两个顶点标签链接在一起。开启这个功能可以配置schema.constrains=true, 默认是false,且schema.default=none。当违反结构约束,会抛出IllegalArgumentException。
约束只在数据插入时有效,数据读取不受约束影响。
mgmt = graph.openManagement()
person = mgmt.makeVertexLabel('person').make()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SET).make()
birthDate = mgmt.makePropertyKey('birthDate').dataType(Long.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
mgmt.addProperties(person, name, birthDate)
mgmt.commit()
mgmt = graph.openManagement()
visit = mgmt.makeEdgeLabel('visit').multiplicity(MULTI).make()
name = mgmt.makePropertyKey('time').dataType(Long.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
mgmt.addProperties(visit, name)
mgmt.commit()
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()
参考资料:
https://github.com/JanusGraph/janusgraph/blob/master/docs/basics/schema.md