图数据库与Gremlin

  • 图数据库是非关系型数据库(noSQL)的一种,利用实体间的对应关系来存储数据。
  • Gremlin语言是图数据库最主流的查询语言。其地位就相当于关系型数据库的SQL。

本文将以hugeGraph图数据库为例来介绍Gremlin语言的基本语法和相关操作。

基本语法

最最基础的语法

tips:

  • Gremlin中的 " 和 ’ 是等价的
查询节点
命令效果
g.V()查询所有节点信息,g表示整张图,一切的查询都是以图开始
g.V("1:abc@qq.com")根据节点信息查询相应节点,引号中的1表示节点的类型所对应的序号,通常是在groovy文件中添加的第一种节点类型;abc@qq.com是要查询的节点的主键
g.V("1:abc@qq.com","2:100")多条查询可以使用逗号隔开
g.V().id()查询所有节点对应的id,返回属性是一个列表
g.V().label()查询所有节点对应的label,返回属性是一个列表
g.V().properties()查询所有结点的属性
g.V().properties("name")查询所有结点的name属性,若没有则跳过
g.V().properties().key()查询所有节点属性的key值
g.V().properties().value()查询所有节点属性的value值
g.V().valueMap()查询所有节点的属性,返回值是一对对键值对
g.V().values()查询所有节点的value值,等同于g.V().properties().value()
查询边
命令效果
g.E()查询所有边的信息
b.E("S1:abc@qq.com>1>>S2:100")根据边的类型,其实就是边的id查询相应边
g.E().label()查询所有边对应的label,返回属性是一个列表
g.E().properties()查询所有边的属性
g.E().properties("name")查询所有边的name属性,若没有则跳过
g.E().properties().key()查询所有边属性的key值
g.E().properties().value()查询所有边属性的value值
g.E().valueMap()查询所有边的属性,返回值是一对对键值对
g.E().values()查询所有边的value值,等同于g.E().properties().value()

边的遍历

命令效果
g.V().in()先查询所有的节点,再找到每个节点的父节点。注意:图数据库不会为其结果自动去重!
g.V().out()先查询所有节点,再找到每个节点的子节点
g.V("1:abc@qq.com").out()找到abc@qq.com节点的子节点
g.V("1:abc@qq.com").out("buy")找到abc@qq.com节点的子节点,且要求该子节点与abc@qq.com之间的边的label是buy
g.V("1:abc@qq.com").both()查询和其相邻的节点,即in()和out()的并集
g.V("1:abc@qq.com").outE()找到以abc@qq.com为起点的边
g.V("1:abc@qq.com").inE()找到以abc@qq.com为终点的边
g.V("1:abc@qq.com").outE("buy")找到以abc@qq.com为起点的,label为buy的边
g.V("1:abc@qq.com").bothE()找到和abc@qq.com相连的所有边
g.E().inV()先找到所有边,再找每条边的终点。
注意:inV()表示终点,outV()表示起点
通常g.V().inE().outV() = g.V().in()
g.E().outV()先找到所有边,再找每条边的起点。
注意:inV()表示终点,outV()表示起点
通常g.V().outE().inV() = g.V().out()
g.E().bothV()找到所有有边的顶点
g.V("1:abc@qq.com").inE().otherV()找到以abc@qq.com为终点的边的另一端顶点,即等价于in()

has条件过滤

在HugeGraph中,按property的值查询之前,应该对property建立索引,否则将无法查到结果并引发异常。(有两个例外,Vertex的PrimaryKeys和Edge的SortKeys,具体参见HugeGraph官网)

  • 使用has系列命令之前,需要在schema中添加索引(不包含主键索引),如下所示,表示为person类型的节点添加address的索引。
    graph.schema().indexLabel('person_address').onV('person').by('address').secondary().ifNotExist().create()
命令效果
g.V().hasLabel("person")查询拥有person标签的节点
g.V().hasLabel("person","email")查询拥有person或email标签的节点。
注意:gremlin中的逗号表示或运算
g.V().hasId("1")查询id为1的节点
g.V().has("name","paul")查询name字段为paul的节点
g.V().has("person","name","paul")查询label为person且name字段为paul的节点
g.V().has("age",gt(30))查询age字段大于30的节点
g.V().properties().haskey("name")查询所有属性中有name字段的节点
注意:当后端是Cassandra时,可用g.V().haskey(“name”)
g.V().properties().hasValue("Beijing")查询所有属性值为Beijing的节点
注意:当后端是Cassandra时,可用g.V().hasValue(“Beijing”)
g.V().has("name")查询有name字段的所有节点
g.V().hasNot("name")查询没有name字段的所有节点

设置查询的数量限制

命令效果
g.V().count()所有结点的数量
g.V().hasLabel("name").count()所有label为name的节点的数量
g.V().properties().count()查询所有节点的属性总数
g.V().hasLabel("name").range(0, -1)查询所有节点中的第一个到最后一个,和python的range语法相同
g.V().limit(9)查询前9个节点
g.E().tail(3)查询后3条边
g.V().hasLabel("name").skip(2)跳过前两条数据,相当于g.V().hasLabel(“name”).range(2, -1)

path查询路径

命令效果
g.V("1:abc@qq.com").both().path()查询和abc@qq.com相邻的所有节点,随后输出其路径,注意只包含节点信息
g.V("1:abc@qq.com").bothE().otherV().path()查询和abc@qq.com相邻的所有节点,随后输出其路径,注意包含节点和边的信息
g.V("1:abc@qq.com").bothE().otherV().path().by("name")查询路径,并使用name属性来代替显示出的字段
g.V("1:abc@qq.com").both().both().simplePath().path()过滤环路
g.V("1:abc@qq.com").both().both().cyclicPath().path()只要环路

循环语句

命令效果
g.V("2:100").repeat(out()).times(2)相当于g.V("2:100").out().out()
g.V("1:abc@qq.com").repeat(out()).until(has("money","100")).path()查询一条从abc@qq.com出发的路径,终点是money为100的节点
g.V("1:abc@qq.com").repeat(out()).emit().path()找到所有abc@qq.com可达的节点,emit()能够记录中间过程,其内可以添加条件
g.V("1:abc@qq.com").repeat(out())
.until(has("money","100")).emit().path()
查询一条从abc@qq.com出发的路径,终点是money为100的节点,期间记录所有中间节点
g.V("2:100").repeat(out()).until(loops().is(3))查询所有三度可达节点
g.V("2:100").repeat(out()).until(loops().is(3)).and(has("name"))查询所有三度可达节点,并且其含有name字段

排序

命令效果
g.V().values('name').order()默认按照升序排序
g.V().values('name').order().by(decr)指定降序
g.V().values('name').order().by(incr)指定升序
g.V().values('name').order().by(shuffle)随机排序
g.V().hasLabel('person').order().by('age')按照某一字段排序
g.V().hasLabel('person').order().by('age', incr).values('age')将person类型的顶点按照age升序排列,并获取age属性

分组与去重

命令效果
g.V().hasLabel("person").group()分组
g.V().hasLabel("person").group().by('age')按年龄分组
g.V().hasLabel("person").group().by('age').by(count())按年龄分组,按数量显示
g.V().group().by(label).by(count())按标签将节点分组,并输出数量
g.V().hasLabel('person').groupCount()分组计数
g.V().hasLabel('person').groupCount().by('age')按年龄分组计数
g.V().both().hasLabel('person').dedup()同顶点去重
g.V().hasLabel('person').values('age').dedup()按年龄去重
g.V().hasLabel('person').dedup().by('age')从各个年龄的人中选出一个代表
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐