每個JanusGraph都有一個schema,該schema由edge labels, property keys和vertex labels組成。JanusGraph的schema可以顯式或隱式創建,推薦用戶采用顯式定義的方式。
JanusGraph的schema是可以在使用過程中修改的,而且不會導致服務宕機,也不會拖慢查詢速度。
注意:通關系型數據庫不同,圖數據的schema是定義一張圖,而非定義一個vertex的。在Mysql中,我們通常將建立一張表定義為創建一個schema,而在JanusGraph中,一個Graph用於一個schema。
組成結構如下:
JanusGraph Schema
|
|-----------Vertex Lables
|
|-----------Property Keys
|
|-----------Edge Labels
Schema Type如edge label, vertex label及property key在元素首次創建時被賦予元素,且不能修改。
Definging Edge Labels
每個連接了兩個vertex的edge都有一個label,用於表示關系的語義。例如一個edge label:friend表明了兩個vertex有朋友關系。
要定義edge lable,調用makeEdgeLabel(String)方法,該方法返回一個builder,可以通過該builder設置edge的多樣性(multiplicity),多樣性屬性定義了具有該label的edge的多樣性約束,也即在一個vertex間的最大edge的個數。JanusGraph支持如下多樣性。
Edge Label Multiplicity(邊的標簽多樣性)
- MULTI
在一對vertex間可以有任意多個同樣label的edge。
- SIMPLE
在一對vertex間最多只能有一個同樣label的edge。
- MANY2ONE
圖中任意一個Vertex最多有一個出度(outgoing)edge,和不限個數的入度(incoming)edge,注意:這些對edge的限制對同一個label生效。
例如:
Label: mother
(大兒子)---------------------------------->|
(二兒子)---------------------------------->|------------------------>(母親)
(小兒子)---------------------------------->|
- ONE2MANY
圖中任意一個Vertex最多有一個入度(incoming)edge,和不限個數的出度(outgoing)edge,注意:這些對edge的限制對同一個label生效。
例如:
Label:winnerof
|-------------------------->(game1)
(person)--------------------------->|-------------------------->(game2)
|-------------------------->(game3)
- ONE2ONE
某verex中具有同樣Label的edge,只能有最多一個incoming edge和最多一個outgoing edge。
默認的多樣性設置為MULTI,設置方法如下所示:
mgmt = graph.openManagement() follow = mgmt.makeEdgeLabel('follow').multiplicity(MULTI).make() mother = mgmt.makeEdgeLabel('mother').multiplicity(MANY2ONE).make() mgmt.commit()
Defining Property Keys
vertex和edge上的property是鍵值對,如name="Danie",中name就是鍵,value則是Danie,Property Key是Graph Schema中的一部分,並且也用約束value的值類型。
Property Key Data Type
使用dataType定義某個property key的數據類型,JanusGraph強制具有相同Key的value都有相同的數據類型來保證加入到圖中的數據是有效的。
可以將某個property key的數據類型定義為Object.class來使該value存儲任何值(可序列化的),但是還是推薦使用具有具體類型的值類型。設置的類的名稱必須是一個確切的類而且不能是接口或抽閑類。JanusGraph提供了class 相等性,所有設置為子類型也是不可以的。
JanusGraph提供如下的數據類型:

Property Key Cardinality(屬性key基數)
使用cardinality(Cardinality)來定義Vertex上某個指定key的value的基數。
- SINGLE
每個KEY只允許一個VALUE
- LIST
以LIST形式保存VALUE,也即可以有重復值。
- SET
以SET形式保存VALUE,不能有重復值。
默認的cardinality是SINGLE,因此試圖向默認property中寫入多個值是不可以的。
mgmt = graph.openManagement() //創建了一個名字為birthDate的屬性,並設置值類型為LONG,且只能保存一個值 birthDate = mgmt.makePropertyKey('birthDate').dataType(Long.class).cardinality(Cardinality.SINGLE).make() //創建了一個名字為name的屬性,並設置值類型為String,且可以保存不能重復的多個值 name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(Cardinality.SET).make() //創建了一個名字為sensorReading的屬性,並設置值類型為Double,且可以保存可以重復的多個值 sensorReading = mgmt.makePropertyKey('sensorReading').dataType(Double.class).cardinality(Cardinality.LIST).make() mgmt.commit()
Relation Types
Edge Labels和property keys結合起來被稱為relation types,relation type的在圖中必須唯一,也意味着property key和edge label不能有相同的名字。在JanusGraph中有查詢relation type的API。
mgmt = graph.openManagement() if(mgmt.containsRelationType('name')) name = mgmt.getPropertyKey('name') mgmt.getRelationTypes(EdgeLabel.class) mgmt.commit()
Defining Vertex Labels
類似於edge,vertex也有label,但與edge不同的是,edge label是可選的,可用於區分不同類型的vertex,如user vertex和product vertex。
雖然vertex label無論在概念還是數據模型層面都是可選的,但JanusGraph為所有的vertex都指定了一個label,addVertex()方法創建的vertex都使用了janusGraph的默認vertex label。vertex label在graph中必須是唯一的。
下面是創建代碼:
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()
Automatic Schema Maker(自動創建schmea)
如果edge label, property key和vertex label沒有被顯式創建,則會在第一次使用時通過默認
DefaultSchemaMaker創建。
默認的,隱式創建的edge label的multiplicity被設置為MULTI;隱式創建的property key設置為SINGLE,value數據類型為Object.class。用戶可以通過實現和注冊自己的DefaultSchemaMaker來自定義。
強烈建議用戶顯式創建,並配置系統為不支持隱式創建。
schema.default=none
Changing Schema Elements
edge label,property key和vertex label的定義一旦提交到graph就不能修改了,但是schema元素的名字是可以修改的。通過JanusGraphManagement.changeName(JanusGraphSchemaElement, String)。
mgmt = graph.openManagement() place = mgmt.getPropertyKey('place') mgmt.changeName(place,'location') mgmt.commit()
需要注意的是,更新schema element的名稱可能不會立即可見,需要等待JanusGraph同步數據或后端數據同步完成。在更名可能導致沖突的情況下,可能要重啟實例。
如果需要更名,可以先將原來元素改名為新的不存在的元素名稱,然后創建新的schema 元素,但不會影響已經創建的數據,需要通過批處理修改數據。