本文的代码都是java
语言写的,但其风格与gremlin(groovy)
是非常类似的。用户只需要把代码中的变量声明替换成def
或直接去掉, 就能将java
代码转变为groovy
;另外就是每一行语句最后可以不加分号,groovy
认为一行就是一条语句。 用户在HugeGraph-Studio
中编写的gremlin(groovy)
可以参考本文的java
代码,下面会举出几个例子。
HugeGraph-Client 是操作 graph 的总入口,用户必须先创建出 HugeGraph-Client 对象,与 HugeGraph-Server 建立连接(伪连接)后,才能获取到 schema、graph 以及 gremlin 的操作入口对象。
目前 HugeGraph-Client 只允许连接服务端已存在的图,无法自定义图进行创建。其创建方法如下:
// HugeGraphServer地址:"http://localhost:8080" // 图的名称:"hugegraph" HugeClient hugeClient = HugeClient.builder("http://localhost:8080", "hugegraph") .configTimeout(20) // 默认 20s 超时 .configUser("**", "**") // 默认未开启用户权限 .build();
上述创建 HugeClient 的过程如果失败会抛出异常,用户需要try-catch。如果成功则继续获取 schema、graph 以及 gremlin 的 manager。
在HugeGraph - Hubble / Studio
中通过gremlin
来操作时,不需要使用HugeClient
,可以忽略。
SchemaManager 用于管理 HugeGraph 中的四种元数据,分别是PropertyKey(属性类型)、VertexLabel(顶点类型)、EdgeLabel(边类型)和 IndexLabel(索引标签)。在定义元数据信息之前必须先创建 SchemaManager 对象。
用户可使用如下方法获得SchemaManager对象:
SchemaManager schema = hugeClient.schema()
在HugeGraph-Studio
中通过gremlin
创建schema
对象:
schema = graph.schema()
下面分别对三种元数据的定义过程进行介绍。
PropertyKey 用来规范顶点和边的属性的约束,暂不支持定义属性的属性。
PropertyKey 允许定义的约束信息包括:name、datatype、cardinality、userdata,下面逐一介绍。
interface | param | must set |
---|---|---|
propertyKey(String name) | name | y |
interface | Java Class |
---|---|
asText() | String |
asInt() | Integer |
asDate() | Date |
asUuid() | UUID |
asBoolean() | Boolean |
asByte() | Byte |
asBlob() | Byte[] |
asDouble() | Double |
asFloat() | Float |
asLong() | Long |
interface | cardinality | description |
---|---|---|
valueSingle() | single | single value |
valueList() | list | multi-values that allow duplicate value |
valueSet() | set | multi-values that not allow duplicate value |
interface | description |
---|---|
userdata(String key, Object value) | The same key, the latter will cover the former |
schema.propertyKey("name").asText().valueSet().ifNotExist().create()
在HugeGraph-Studio
中通过gremlin
创建上述PropertyKey
对象的语法完全一致,如果用户没有定义出schema
变量,应该这样写:
graph.schema().propertyKey("name").asText().valueSet().ifNotExist().create()
以下的示例中,gremlin
与java
的语法完全一致,不再赘述。
schema.propertyKey("name").remove()
// 获取PropertyKey对象 schema.getPropertyKey("name") // 获取PropertyKey属性 schema.getPropertyKey("name").cardinality() schema.getPropertyKey("name").dataType() schema.getPropertyKey("name").name() schema.getPropertyKey("name").userdata()
VertexLabel 用来定义顶点类型,描述顶点的约束信息:
VertexLabel 允许定义的约束信息包括:name、idStrategy、properties、primaryKeys和 nullableKeys,下面逐一介绍。
interface | param | must set |
---|---|---|
vertexLabel(String name) | name | y |
interface | idStrategy | description |
---|---|---|
useAutomaticId | AUTOMATIC | generate id automaticly by Snowflake algorithom |
useCustomizeStringId | CUSTOMIZE_STRING | passed id by user, must be string type |
useCustomizeNumberId | CUSTOMIZE_NUMBER | passed id by user, must be number type |
usePrimaryKeyId | PRIMARY_KEY | choose some important prop as primary key to splice id |
interface | description |
---|---|
properties(String... properties) | allow to pass multi props |
interface | description |
---|---|
primaryKeys(String... keys) | allow to choose multi prop as primaryKeys |
需要注意的是,Id 策略的选择与 primaryKeys 的设置有一些相互约束,不能随意调用,约束关系见下表:
useAutomaticId | useCustomizeStringId | useCustomizeNumberId | usePrimaryKeyId | |
---|---|---|---|---|
unset primaryKeys | AUTOMATIC | CUSTOMIZE_STRING | CUSTOMIZE_NUMBER | ERROR |
set primaryKeys | ERROR | ERROR | ERROR | PRIMARY_KEY |
interface | description |
---|---|
nullableKeys(String... properties) | allow to pass multi props |
注意:primaryKeys 和 nullableKeys 不能有交集,因为一个属性不能既作为主属性,又是可空的。
g.V().hasLabel('person'), g.E().has('label', 'person')
这样的查询, 但是插入数据时性能上会更加慢,并且需要占用更多的存储空间。此项默认为 true。interface | description |
---|---|
enableLabelIndex(boolean enable) | Whether to create a label index |
interface | description |
---|---|
userdata(String key, Object value) | The same key, the latter will cover the former |
// 使用 Automatic 的 Id 策略 schema.vertexLabel("person").properties("name", "age").ifNotExist().create(); schema.vertexLabel("person").useAutomaticId().properties("name", "age").ifNotExist().create(); // 使用 Customize_String 的 Id 策略 schema.vertexLabel("person").useCustomizeStringId().properties("name", "age").ifNotExist().create(); // 使用 Customize_Number 的 Id 策略 schema.vertexLabel("person").useCustomizeNumberId().properties("name", "age").ifNotExist().create(); // 使用 PrimaryKey 的 Id 策略 schema.vertexLabel("person").properties("name", "age").primaryKeys("name").ifNotExist().create(); schema.vertexLabel("person").usePrimaryKeyId().properties("name", "age").primaryKeys("name").ifNotExist().create();
VertexLabel 是可以追加约束的,不过仅限 properties 和 nullableKeys,而且追加的属性也必须添加到 nullableKeys 集合中。
schema.vertexLabel("person").properties("price").nullableKeys("price").append();
schema.vertexLabel("person").remove();
// 获取VertexLabel对象 schema.getVertexLabel("name") // 获取property key属性 schema.getVertexLabel("person").idStrategy() schema.getVertexLabel("person").primaryKeys() schema.getVertexLabel("person").name() schema.getVertexLabel("person").properties() schema.getVertexLabel("person").nullableKeys() schema.getVertexLabel("person").userdata()
EdgeLabel 用来定义边类型,描述边的约束信息。
EdgeLabel 允许定义的约束信息包括:name、sourceLabel、targetLabel、frequency、properties、sortKeys 和 nullableKeys,下面逐一介绍。
interface | param | must set |
---|---|---|
edgeLabel(String name) | name | y |
sourceLabel: 边连接的源顶点类型名,只允许设置一个;
targetLabel: 边连接的目标顶点类型名,只允许设置一个;
interface | param | must set |
---|---|---|
sourceLabel(String label) | label | y |
targetLabel(String label) | label | y |
interface | frequency | description |
---|---|---|
singleTime() | single | a relationship can only occur once |
multiTimes() | multiple | a relationship can occur many times |
interface | description |
---|---|
properties(String... properties) | allow to pass multi props |
interface | description |
---|---|
sortKeys(String... keys) | allow to choose multi prop as sortKeys |
注意:sortKeys 和 nullableKeys也不能有交集。
enableLabelIndex:与顶点中的 enableLabelIndex 概念一致,不再赘述
userdata:用户可以自己添加一些约束或额外信息,然后自行检查传入的属性是否满足约束,或者必要的时候提取出额外信息
interface | description |
---|---|
userdata(String key, Object value) | The same key, the latter will cover the former |
schema.edgeLabel("knows").link("person", "person").properties("date").ifNotExist().create(); schema.edgeLabel("created").multiTimes().link("person", "software").properties("date").sortKeys("date").ifNotExist().create();
schema.edgeLabel("knows").properties("price").nullableKeys("price").append();
schema.edgeLabel("knows").remove();
// 获取EdgeLabel对象 schema.getEdgeLabel("knows") // 获取property key属性 schema.getEdgeLabel("knows").frequency() schema.getEdgeLabel("knows").sourceLabel() schema.getEdgeLabel("knows").targetLabel() schema.getEdgeLabel("knows").sortKeys() schema.getEdgeLabel("knows").name() schema.getEdgeLabel("knows").properties() schema.getEdgeLabel("knows").nullableKeys() schema.getEdgeLabel("knows").userdata()
IndexLabel 用来定义索引类型,描述索引的约束信息,主要是为了方便查询。
IndexLabel 允许定义的约束信息包括:name、baseType、baseValue、indexFeilds、indexType,下面逐一介绍。
interface | param | must set |
---|---|---|
indexLabel(String name) | name | y |
baseType: 表示要为 VertexLabel 还是 EdgeLabel 建立索引, 与下面的 baseValue 配合使用;
baseValue: 指定要建立索引的 VertexLabel 或 EdgeLabel 的名称;
interface | param | description |
---|---|---|
onV(String baseValue) | baseValue | build index for VertexLabel: ‘baseValue’ |
onE(String baseValue) | baseValue | build index for EdgeLabel: ‘baseValue’ |
interface | param | description |
---|---|---|
by(String... fields) | files | allow to build index for multi fields for secondary index |
g.V().has("city", "北京")
查询“city属性值是北京”的全部顶点g.V().has ("city", "北京").has('street', '中关村街道')
查询“city属性值是北京且street属性值是中关村”的全部顶点,或者g.V() .has("city", "北京")
查询“city属性值是北京”的全部顶点secondary index的查询都是基于“是”或者“相等”的查询条件,不支持“部分匹配”
g.V().has("age", P.gt(18))
查询“age属性值大于18”的顶点。除了P.gt()
以外,还支持P.gte()
, P.lte()
, P.lt()
, P.eq()
, P.between()
, P.inside()
和P.outside()
等g.V().has("address", Text .contains('大厦')
查询“address属性中包含大厦”的全部顶点search index的查询是基于“是”或者“包含”的查询条件
g.V().has ("city", "北京").has("age", P.between(18, 30))
查询“city属性是北京且年龄大于等于18小于30”的全部顶点shard index可以有任意数字或者日期属性,但是查询时最多只能提供一个范围查找条件,且该范围查找条件的属性的前缀属性都是相等查询条件
interface | indexType | description |
---|---|---|
secondary() | Secondary | support prefix search |
range() | Range | support range(numeric or date type) search |
search() | Search | support full text search |
shard() | Shard | support prefix + range(numeric or date type) search |
unique() | Unique | support unique props value, not support search |
schema.indexLabel("personByAge").onV("person").by("age").range().ifNotExist().create(); schema.indexLabel("createdByDate").onE("created").by("date").secondary().ifNotExist().create(); schema.indexLabel("personByLived").onE("person").by("lived").search().ifNotExist().create(); schema.indexLabel("personByCityAndAge").onV("person").by("city", "age").shard().ifNotExist().create(); schema.indexLabel("personById").onV("person").by("id").unique().ifNotExist().create();
schema.indexLabel("personByAge").remove()
// 获取IndexLabel对象 schema.getIndexLabel("personByAge") // 获取property key属性 schema.getIndexLabel("personByAge").baseType() schema.getIndexLabel("personByAge").baseValue() schema.getIndexLabel("personByAge").indexFields() schema.getIndexLabel("personByAge").indexType() schema.getIndexLabel("personByAge").name()
顶点是构成图的最基本元素,一个图中可以有非常多的顶点。下面给出一个添加顶点的例子:
Vertex marko = graph.addVertex(T.label, "person", "name", "marko", "age", 29); Vertex lop = graph.addVertex(T.label, "software", "name", "lop", "lang", "java", "price", 328);
key1 -> val1, key2 -> val2 ···
的顺序排列,键值对之间的顺序是自由的。T.label -> "val"
,用来定义该顶点的类别,以便于程序从缓存或后端获取到该VertexLabel的schema定义,然后做后续的约束检查。例子中的label定义为person。AUTOMATIC
,则不允许用户传入 id 键值对。CUSTOMIZE_STRING
,则用户需要自己传入 String 类型 id 的值,键值对形如:"T.id", "123456"
。CUSTOMIZE_NUMBER
,则用户需要自己传入 Number 类型 id 的值,键值对形如:"T.id", 123456
。PRIMARY_KEY
,参数还必须全部包含该primaryKeys
对应属性的名和值,如果不设置会抛出异常。比如之前person
的primaryKeys
是name
,例子中就设置了name
的值为marko
。addVertex
方法后,顶点会立刻被插入到后端存储系统中。有了点,还需要边才能构成完整的图。下面给出一个添加边的例子:
Edge knows1 = marko.addEdge("knows", vadas, "city", "Beijing");
key1 -> val1, key2 -> val2 ···
的顺序排列,设置边的属性,键值对顺序自由。注意:当frequency为multiple时必须要设置sortKeys对应属性类型的值。
简单示例见HugeGraph-Client