Gremlin是JanusGraph用来修改和查询图数据的语言。Gremlin是一个面向路径的,简洁的对图进行遍历和操作的语言。Gremlin是一个函数式的语言,它的遍历操作可以链接在一起形成一个路径一样的表达式。比如:从Hercules开始,找到他的爸爸,然后找到他爸爸的爸爸,最后返回他爷爷的名字

Gremlin是Apache TinkerPop的一个组件。它是独立于JanusGraph开发的,大多数的图数据库都支持。基于Gremlin开发的应用可以做到存储透明,可以迁移到其他支持Gremlin的图数据库上。

这个文章主要是大概过一下Gremlin,关于Gremlin更详细的内容,可以参考下边的资源:
资源

图的遍历

一个Gremlin的查询是一组可以从左向右进行的操作/方法。一个简单的查找爷爷名字的语句如下:

gremlin> g.V().has('name','hercules').out('father').out('father').values('name')
==>saturn

上边的查询可以这样来读:
1. g:指的是当前的图
2. V:图里所有的顶点
3. has(‘name’,’hercules’): 过滤所有名字为hercules的顶点
4. out(‘father’):从Hercules的顶点沿着father边出去
5. out(‘father’):从Hercules的father的顶点再沿着father边出去
6. values(‘name’):获取Hercules爷爷的名字

就像一个路径一样来构造这个图的遍历,这样在进行复杂查询是非常有用的。

gremlin> g
==>graphtraversalsource[janusgraph[cql:127.0.0.1], standard]
gremlin> g.V().has('name', 'hercules')
==>v[24]
gremlin> g.V().has('name', 'hercules').out('father')
==>v[16]
gremlin> g.V().has('name', 'hercules').out('father').out('father')
==>v[20]
gremlin> g.V().has('name', 'hercules').out('father').out('father').values('name')
==>saturn

我们可以对查询进行检查

gremlin> g.V().has('name', 'hercules').values('name')
==>hercules
gremlin> g.V().has('name', 'hercules').out('father').values('name')
==>jupiter
gremlin> g.V().has('name', 'hercules').out('father').out('father').values('name')
==>saturn

还有更复杂的形式,我们对Hercules的父亲的家谱进行遍历。这个例子展示了JanusGraph的灵活和强大

gremlin> g.V().has('name', 'hercules').repeat(out('father')).emit().values('name')
==>jupiter
==>saturn

还有更多的例子:

gremlin> hercules = g.V().has('name', 'hercules').next()
==>v[1536]
gremlin> g.V(hercules).out('father', 'mother').label()
==>god
==>human
gremlin> g.V(hercules).out('battled').label()
==>monster
==>monster
==>monster
gremlin> g.V(hercules).out('battled').valueMap()
==>{name=nemean}
==>{name=hydra}
==>{name=cerberus}

通过点来间隔的每个step都是对前一步的输出的继续处理。Gremlin里有很多step Gremlin Steps 通过使用和组合不同的step,可以实现不同的语义逻辑。比如下边的例子查询了所有和Hercules打过同一个怪兽但不是Hercules本人的所有人。也就是Hercules的战友。

但是在诸神图里只有Hercules一个战士,我们下边演示一下如何用Gremlin把顶点和边加入到图里。

gremlin> theseus = graph.addVertex('human')
==>v[3328]
gremlin> theseus.peroperty('name','theseus')
==>null
gremlin> cerberus = g.V().has('name','cerberus').next()
==>[2816]
gremlin> battle = theseus.addEdge('battled',cerberus,'time',22)
==>e[7eo-2kg-iz9-268][3328-battled->2816]
gremlin> battle.values('time')
==>22

当我们添加一个顶点的时候,可以选择添加一个Vertex label。但是添加一个边的时候必须指定一个label。key-value对这样形式的属性值可以被设置在边和顶点上。当一个属性值的基数是Set或者List。必须用addProperty来给顶点添加相应的属性。

gremlin> g.V(hercules).as('h').out('battled').in('battled').where(neq('h')).values('name')
==>theseus

上边的例子链接了4个方法:out,in,except,values。方法的签名如下.V是一个vertex,U是任意的Object。V是U的子类
1. out: V->V
2. in:V->V
3. except:U->U
4. values:V->U

当方法串起来的时候,输入类型必须和上一步的输出类型匹配。因为U和任意类型匹配。所以对于“战友”的图遍历是正确的。

这里演示的是Gremlin-Groovy语言的,Gremlin也支持其他语言。

对遍历迭代

在Gremlin Console里可以自动对结果遍历显示,想要在程序里遍历结果有以下一些方法:
1. iterate() 期待有零个结果或者结果可以被忽略
2. next() 得到一个结果,必须先用hasNext确定是否有next
3. next(int n) 获取next n个元素
4. toList() 将所有结果以List 形式返回

java代码的例子:

Traversal t = g.V().has("name", "pluto"); // Define a traversal
// Note the traversal is not executed/iterated yet
Vertex pluto = null;
if (t.hasNext()) { // Check if results are available
    pluto = g.V().has("name", "pluto").next(); // Get one result
    g.V(pluto).drop().iterate(); // Execute a traversal to drop pluto from graph
}
// Note the traversal can be cloned for reuse
Traversal tt = t.asAdmin().clone();
if (tt.hasNext()) {
    System.err.println("pluto was not dropped!");
}
List<Vertex> gods = g.V().hasLabel("god").toList(); // Find all the gods

发表评论

电子邮件地址不会被公开。 必填项已用*标注

%d 博主赞过: