图查询语言——Gremlin

参考:https://blog.csdn.net/CSDN___LYY/article/details/84771820 

背景:

目前图数据库领域最主流的两种查询语言为 Cypher 和 Gremlin。Cypher 是数据库Neo4j中实现的属性图数据查询语言。与SPARQL一样,Cypher 也是一种声明式语言,即用户只需要声明“查什么”,而无须关心“怎么查”。

Gremlin是Apache TinkerPop图计算框架提供的属性图查询语言。 Apache TinkerPop被设计为访问图数据库的通用API接口,其作用类似于关系数据库上的JDBC接口。Gremlin的定位是图遍历语言,其执行机制好比是一个人置身于图中沿着有向边,从一个节点到另一个节点进行导航式的游走。这种执行方式决定了用户使用Gremlin需要指明具体的导航步骤。

由于的笔者设计的知识图谱后端存储方案是利用janusgraph图数据库,而janusgraph使用的查询语言是Gremlin,本文重点针对对Gremlin的学习。

图数据模型示例:

  

一:gremlin查询过程

gremlin的查询是流式查询,一步一步的进行下去,当然这里的“一步”可能是一个方法(g.V().has())也可能是多个方法组成的一步(g.V().order().by(desc,‘age’))。下面看一个案例

g.V().has('code','AUS').out().value('name','age').order().by('age',desc)

步骤解读
第一步:g.V() 标明是对图库中的所有节点进行操作的
第二步:has(‘code’,‘AUS’) 获取包含属性code并且该属性的值为AUS的所有节点
第三步:out() 获取上个结果集中所有节点的出边对应的节点
第四步:value(‘name’,‘age’) 获取上个结果集中所有节点的name和age属性值
第五步:order().by(‘age’,desc) 对结果集根据age进行降序排序
从上面便可以看出gremlin流式执行的特征,这使得gremlin的查询语句可以十分的灵活,从而满足我们的各种查询需求。想要了解更多全面的查询方法,可以看英文官网:http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html#_introduction

二:常用的查询方法

1、首先,这里的g.V()中的g为遍历实例,其创建为:

graph = TinkerGraph.open()
g = graph.traversal() 

2、V()与E()

在下面的例子中,你会发现几乎每一个查询的开始都会有他们的存在
V()代表查看图中的所有节点,接下来的操作是对节点进行操作的
E()代表图中的所有边,接下来的操作就是对边操作的

3、使用value获取节点的某一个属性值

g.V().has('code','AUS').out().value('name','age')
//获取AUS的出边对应节点的name和age属性的值
g.V().has('code','AUS').out().value()
//显示所有的属性值

4、使用has、hasNot获取(不)包含某一属性值的节点

g.V().has('code','AUS')
//获取拥有code属性并且其属性值为AUS的节点
g.V().has('user','code','AUS')
//相当于 g.V().hasLabel('user').has('code','AUS')
g.V().hasNot('name')
//获取所有不包含name属性的节点,等同于g.V().not(has('name'))

5、使用 hasLabel获取label为某值得节点

g.V().hasLabel("user")
//获取label为user的节点

6、使用hasNext方法判断两个节点中是否有查询的边

  • 返回值为boolean类型参数,存在则返回true,不存在则false
g.V().has('code','AUS').out('route').has('code','DFW').hasNext()

true

g.V().has('code','AUS').out('route').has('code','SYD').hasNext()

false

7、使用range()获取某一范围内的数据

g.V().hasLabel('airport').range(0,2)
//输出结果集中1,2个节点
g.V().hasLabel('airport').range(3,6)
//输出结果集中4,5,6个节点
g.V().range(3500,-1)
//输出结果集中3500往后的所有节点

8、使用skip跳跃节点查找

g.V().has('region','US-TX').skip(5)
//跳过节点集中的前5条数据,从第六条开始,效果等同于下面的语句
g.V().has('region','US-TX').range(5,-1)

9、使用order对结果集进行排序

g.V().has('code','AUS').out().order().by()
g.V().has('code','AUS').out().order(local).
g.V().has('code','AUS').out()
g.V().has('code','AUS').out()

order(local)中local的作用:Notice also how local is used as a parameter to order. This is required so that the ordering is done while the final list is being constructed. If you do not specify local then order will have no effect as it will be applied to the entire result which is treated as a single entity at that point. 这是官网上的一句话,我翻译了一下没太明白,大体的意思我理解的是:加local参数的话会在最终结果生成前就完成排序。。大家可以翻译一下
 

10、使用 out,in进行查找结点的出边和入边所对应的节点

g.V().has('code','AUS').out()
//获取AUS的节点所有出边对应的节点
g.V().has('code','AUS').out("brought")
//获取AUS节点所有边关系为“brought”的出边对应的节点
g.V().has('code','AUS').in()
//获取AUS的节点所有入边对应的节点
g.V().has('code','AUS').in("brought")
//获取AUS节点所有边关系为“brought”的入边对应的节点

11、使用count、groupCount对结果集计数

g.V().has('code','AUS').out().count()
//获取AUS节点的出边的个数
g.V().has('code','AUS').out().groupCount().by("name")
//根据结果集的name属性的值进行分组计数,最终结果类似于:[a:1,b:3,r:6]

12、使用dedup进行去重

g.V().has('code','AUS').out().out().dedup().count()
//步骤解读:
1:获取AUS节点的两度出节点,用dedup对结果进行去重
2:使用count()对结果集进行计数

 

Guess you like

Origin blog.csdn.net/chenxy02/article/details/107158711