一、属性、顶点、边操作
1、创建属性 PropertyKey
// 创建name属性,数据类型为 text,基数默认
graph.schema().propertyKey("name").asText().ifNotExist().create()
// 创建name属性,数据类型为 int,基数默认
graph.schema().propertyKey("age").asInt().ifNotExist().create()
// other,数据类型为text,基数为set
graph.schema().propertyKey("other").asText().valueSet().ifNotExist().create()
2、创建顶点
// 创建person顶点,属性为name,age,使用自定义数字id策略,name不能为空
graph.schema().vertexLabel("person").properties("name", "age").useCustomizeNumberId().nullableKeys("name").ifNotExist().create()
// 使用 PrimaryKey Id策略 graph.schema().vertexLabel("person").properties("name","age").primaryKeys("name").ifNotExist().create();
graph.schema().vertexLabel("person").usePrimaryKeyId().properties("name","age").primaryKeys("name").ifNotExist().create();
// 使用自动生成id
graph.schema().vertexLabel("人员").properties("坐标_经度","姓名","出生日期","坐标_纬度").nullableKeys("坐标_经度","出生日期","坐标_纬度").useAutomaticId().ifNotExist().create()
// 使用自定义字符串
graph.schema().vertexLabel("person").properties("name", "age", "addr", "weight").useCustomizeStringId().ifNotExist().create()
3、创建边
// 边关系为person到person的边,名称relation,边属性为relation
graph.schema().edgeLabel("relation").sourceLabel("person").targetLabel("person").properties("relation").ifNotExist().create()
4、添加数据
// T.label 为顶点名,T.id 为自定义主键数字
graph.addVertex(T.label, "person", T.id, 2001,"name", "巴达克", "age", 100)
graph.addVertex(T.label, "person", T.id, 2002,"name", "孙悟空", "age", 40)
// addV('company') 为指定顶点类型 company, property('name', '中石油') 为kv属性及值
g.addV('company').property('name', '中石油').property('city', '北京').property('addr', '中国北京市高新区')
// 使用自定义字符串主键加 property(id, 'java')
g.addV('software').property('name', 'java').property('weight', 1).property(id, 'java')
// 使用自定义字符串主键加 property(id, 'java')
g.addV('software').property('name', 'java').property('weight', 1).property(id, 'java')
// 使用 PrimaryKey Id策略时,id主键 不能设置 T.id
graph.addVertex(T.label, "software", "id", 111, "name", "java", "weight", "1")
// 使用 PrimaryKey Id策略时,非id主键策略,自定义数字策略,显式设置T.id
graph.addVertex(T.label, "person", T.id, 111, "id", 111,"name", "marko", "age", 29, "sex", "男", "addr", "陕西西安", "weight", "1")
5、绑定关系
// 方法一
g.V(2001).addE('relation').to(g.V(2002)).property('relation','儿子')
g.V(2002).addE('relation').to(g.V(2002)).property('relation','父亲')
// 方法二
to = g.V(2001)
from = g.V(2002)
g.addE('relation').from(from).to(to).property('relation','父亲')
// 方法三
javeme = graph.addVertex(T.label, "person", T.id, "javeme", "name", "Jermy Li", "age", 29, "addr", "Beijing", "weight", 1)
zhoney = graph.addVertex(T.label, "person", T.id, "zhoney", "name", "Zhoney Zhang", "age", 29, "addr", "Beijing", "weight", 1)
javeme.addEdge("knows", zhoney, "weight", 1)
6、创建索引
// 范围索引
graph.schema().indexLabel('personByAgeRange').onV('person').by('age').range().ifNotExist().create()
// 二级索引
graph.schema().indexLabel('personByName').onV('person').by('name').secondary().ifNotExist().create()
// 全文索引
graph.schema().indexLabel('personByNameFull').onV('person').by('age').search().ifNotExist().create()
// 索引类型
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
7、删除
-- 删除顶点
g.V('600').drop()
-- 删除边关系
g.E(id).drop()
-- 删除索引
schema.indexLabel("personByAge").remove()
二、查询
1、日期类型查询
// 使用where查询日期
g.V().hasLabel('person').where(values('创建时间').is(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse('1990-07-01 00:00:00.000')))
// 使用filter查询日期
g.V().hasLabel('person').filter {it.get().value('创建时间') == new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse('1990-07-01 00:00:00.000')}
// 将日期属性转化为日期字符串比较
g.V().hasLabel("person").filter{new java.text.SimpleDateFormat("yyyy-MM-dd").format(it.get().value("创建时间")) == '1990-07-01'}
2、条件查询 多条件or和and组合查询
// 多条件or和and组合查询
g.V()
.hasLabel('古建筑', '企业', '人')
.or(
and(values('地理_经度').is(gt(116.38571098899912)), values('地理_经度').is(lt(116.42085172218476)), values('地理_纬度').is(gt(39.910126452476156)), values('地理_纬度').is(lt(39.937075910999745))),
and(values('经度').is(gt(116.38571098899912)), values('经度').is(lt(116.42085172218476)), values('纬度').is(gt(39.910126452476156)), values('纬度').is(lt(39.937075910999745)))
)
.where(
values('地址').is(eq('北京市'))
)
3、查询顶点信息
1、查询
g.V()
2、查询所有点,但限制点的返回数量
g.V().limit(5)
3、使用range(x, y)的算子,返回区间内的点数量
g.V().range(0,5)
4、查找label值的节点数据
g.V().hasLabel('person')
5、通过id查询节点
g.V('javeme')
6、 查询点的name属性
g.V().values('name')
7、dedup() (filter) 单步可以用来在整个遍历流中去重。 注意如果一个遍历的批量如果大于1,那么它在发出前就被设置成1了
g.V().values('age').dedup()
8、查询指定节点出度out(label):根据指定的 Edge Label 来访问顶点的 OUT 方向邻接点
查询一级出度
g.V('8').out()
查询二级出度
g.V('8').out().out()
查询顶点id='javeme'所有边中向外指的顶点,返回这些顶点的name的值
g.V('javeme').out().values('name')
.V()查询定点, .out() 输出的顶点,.values("name") 属性为name的值
9、path() 单步来检测它的路径实现
g.V('8').out().out().dedup().path()
10、获得经过的边的信息 bothE().otherV()
g.V('8').out().out().bothE().otherV().path()
11、simplePath(),过滤掉路径中含有环路的对象,只保留路径中不含有环路的对象
g.V('8').out().out().simplePath()
12、cyclicPath(),过滤掉路径中不含有环路的对象,只保留路径中含有环路的对象
g.V('8').out().out().cyclicPath()
13、统计
g.V('8').out().out().count()
14、使用map的方式,查询顶点id='javeme'所有边中向外指的顶点,返回这些顶点的name的值
g.V('javeme').out().map {it.get().value('name')}
和上面的区别在于,value中的属性必须都有,否则报错,而.values("name")属性不存在会忽略
g.V('javeme').out().map(values('name'))
15、删除节点
g.V('600').drop()
16、查询点的所有属性
g.V().limit(3).valueMap()
17、查询点的所有label
g.V().label()
18、获取顶点、边的属性值
g.V().properties().value()
g.V().values()
19、properties():获取顶点、边的属性
g.V().properties('name')
20、in(label) 顶点为基准 根据指定的 Edge Label 来访问顶点的 IN 方向邻接点
g.V('zhoney').in()
g.V('zhoney').in('knows')
21、both(label) 顶点为基准 根据指定的 Edge Label 来访问顶点的双向邻接点
g.V('zhoney').both()
g.V('zhoney').both('knows')
22、bothV() 以边为基准 访问边的双向顶点
g.E('Sokram>9>>Szhoney').bothV()
23、outV() 以边为基准 访问边的出顶点,出顶点是指边的起始顶点
g.E('Sokram>9>>Szhoney').outV()
24、inV() 以边为基准 访问边的入顶点,入顶点是指边的目标顶点,也就是箭头指向的顶点
g.E('Sokram>9>>Szhoney').inV()
25、otherV() 以边为基准 访问边的伙伴顶点
g.V('zhoney').outE().otherV()
26、valueMap() 输出属性的key-value对
g.V(2002).valueMap()
27、select(key1,...,keyN)从map中取出需要的属性
g.V(2002).valueMap().select("name", "identity")
28、properties() 查询属性,对每个顶点/边返回一个mapping
g.V(2002).properties()
29、values(key1,...,keyN)取出节点/边的属性,返回列表
g.V(2002).values() 返回所有属性值
g.V(2002).values('name', 'age') 返回指定属性值
30、tail(N) 尾部截取N个数据
g.V().tail(10) 取最后10条数据
g.V().tail() 取最后一条数据
4、查询边信息
1、查询所有边
g.E()
2、查询指定数量边
g.E().limit(4)
3、查询指定区间边
g.E().range(2,4)
4、通过边id查询
g.E('S8:中石油>6>>Szhoney')
5、通过边类型查询边
g.E().hasLabel('use')
6、删除边
g.E('S8:中石油>6>>Szhoney').drop()
7、顶点为基准 查询某个点的指定出边
g.V('okram').outE()
查询某个顶点 use 出边
g.V('okram').outE('use')
8、顶点为基准 查询某个点的指定入边
g.V('zhoney').inE()
查询某个顶点 use 入边
g.V('zhoney').inE('staff')
9、顶点为基准 bothE(label) 根据指定的 Edge Label 来访问顶点的双向邻接边
g.V('zhoney').bothE()
g.V('zhoney').bothE('knows')
三、has的用法类似于过滤器的作用
在HugeGraph中,按property的值查询之前,应该对property建立索引,否则将无法查到结果并引发异常,
如下,执行下面语句报错
g.V().has('name', 'Marko A. Rodriguez').next()
异常:
Gremlin 执行失败,详细信息: Don't accept query based on properties [name] that are not indexed in any label, may not match secondary condition
解决方法:
对person的name属性建立secondary索引,可以对Text类型property按值进行查询
graph.schema().indexLabel('personByName').onV('person').by('name').secondary().ifNotExist().create()
1、查找所有顶点中label边的值为person的(默认返回节点信息)
g.V().hasLabel('person')
2、一个过滤器(filter)操作,过滤条件是顶点的标签是"person"
g.V().filter(label().is('person')).limit(100)
可能会报 Gremlin 执行失败,详细信息: Too many records(must <= 800000) for the query: `Query * from VERTEX`
3、通过name属性查询 (前提条件建立索引)
g.V().has('name', 'Zhoney Zhang')
精确查询集合内的数据
g.V().has('name', within('Marko A. Rodriguez', 'Zhoney Zhang'))
查询年龄29的定点
g.V().has('age', 29)
4、hasKey(keys…) 通过 properties 中的若干 key 过滤顶点或边
g.V().properties().hasKey('age')
5、hasValue(values…): 通过 properties 中的若干 value 过滤顶点或边
g.V().properties().hasValue(29)
6、has(key) properties 中存在 key 这个属性则通过,等价于hasKey(key)
g.V().has('age')
四、where查询
g.V().hasLabel('人').where(values('名称').is(eq('秦始皇')).and().values('年龄').is(eq(60)))
g.V(613794531921362945).both().hasLabel('企业').both('历史').where(has('地理_纬度').and().has('创建时间').and().values('创建时间').is(gt(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse('2011-07-01 00:00:00')))).order().by('创建时间')
g.V(613794531921362945).both().hasLabel('企业').both('历史').where(has('地理_纬度').and().has('创建时间')).order().by('创建时间')
类似其他语法中有比较值或值的范围的语句,gremlin中这类比较语句的Predicates
1、eq() 等于
2、neq() 不等于
3、gt() 大于
4、gte() 大于或等于
5、lt() 小于
6、lte() 小于或等于
7、inside(a, b) 是否在开区间(a, b)
8、outside(a,b) 是否在开区间(a,b)外
9、between(a, b) 是否在区间[a, b)内
10、within 是否在list/range中
11、without 是否在/list/range外
五、使用hugeGraph创建数据库
1、进入服务安装目录
2、在 /conf 目录下创建 hugemysql2.properties 配置文件,并修改自己的数据库信息
3、修改 rest-server.properties 在 graphs=[hugemysql: conf/hugemysql.properties] 添加配置信息
4、修改 gremlin-server.yaml,在 graphs 标签中添加配置文件路径
graphs: {
hugemysql2: conf/hugemysql2.properties
}
5、进入 bin 目录,停止服务 sh stop-hugegraph.sh
6、安装服务,sh init-store.sh
7、重启服务,sh start-hugegraph.sh
8、在页面新建连接
六、问题
1、Gremlin 执行失败,详细信息: Don't accept query based on properties [name] that are not indexed in any label, may not match secondary condition
解决方法
对person的name属性建立secondary索引,可以对Text类型property按值进行查询
graph.schema().indexLabel('personByName').onV('person').by('name').secondary().ifNotExist().create()
2、Gremlin 执行失败,详细信息: Don't accept query based on properties [age] that are not indexed in any label, may not match range condition
3、Gremlin 执行失败,详细信息: Don't accept query based on properties [name] that are not indexed in any label, may not match not-equal condition
g.V().has('name',without('java','Zhoney Zhang')) 报错 within 可以,without不行