知识图谱与图数据库

Chapter 6. Gremlin Query Languag

2019-06-26  本文已影响0人  水他
Gremlin

Gremlin是janusgraph的查询语言,用来获取/变更图数据。Gremlin是一个面向path的语言,能够简单快速的完成图遍历和变化操作。Gremlin是一个功能性语言,因此遍历操作被声明到类path的表达式表单。例如,from Hercules, traverse to his father and then his father’s father and return the grandfather’s name

Gremlin是Apache TinkerPop的组件。它独立于janusgraph发展,并且被支持于大多数图数据库。建在janusgraph上的应用程序通过Gremlin查询语言,用户避免被发行商锁在一个图数据库上。

这章是Gremlin查询语言的简要概述。更多信息可以参考以下资源:

6.1 图遍历的介绍

一次Gremlin查询是一串从左到右的操作/函数链。下面是一个上帝图里举过的祖父查询例子:

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

上面的查询可以分成以下步骤:

  1. g: 当前graph。
  2. V: graph中所有顶点。
  3. has('name', 'hercules'): 过滤出顶点有属性name = "hercules" (这里只有一个)。
  4. out('father'): 从Hercules遍历出边(outgoing edge)为father的顶点。
  5. out('father'): 从Hercules的father (Jupiter)遍历出边为father的顶点。
  6. name: 拿出顶点的name属性的value。

放到一起,这些步骤构成了类似遍历查询的路径。每一步都能分解且得到结果。当构造大型、复杂的查询链,这种图遍历/查询的风格是很有用的。

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

正常情况,通常看到返回的属性更好,而不是分配的id。

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

下面例子显示了完整的father家族树。这个复杂些的例子说明了这个语言的灵活性和便利性。熟练掌握Gremlin使得用户使用junasgraph图结构如鱼得水。

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}

每一步(.分开)是一个函数,操作前一步结果的对象,Gremlin有很多步骤Gremlin steps。简单的改变一个步骤或步骤的顺序,会执行不同的遍历语义,下面的例子是和Hercules打过同样的怪兽,但不是Hercules的所有人的name。(类似战友、盟友)
给定的上帝图只有一个和怪兽战斗的,所以这里增加一个战士到图里。

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

当增加顶点时,顶点的label是选填。增加边时label必须提供。顶点或边都可以设置kv对的属性。当一个属性key的种类设置为SET或LIST,这个key的属性每一个必须用addProperty增加到顶点。

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

这个例子有4个链的函数,out, in, except, 和values,每个函数的输入输出类型如下表,V是顶点,U是Object,V是U的子集。

  1. out: V -> V
  2. in: V -> V
  3. except: U -> U
  4. values: V -> U

当把函数连起来,输入类型必须等于输出类型,U匹配所有。

注意

这样的Gremlin说的是在Gremlin
Console用的Gremlin-Groovy。Gremlin也有其他的语言支持drivers,variants

6.2 执行遍历

Gremlin Console的一个方便的特性是它自动生成所有结果,从终端执行查询。它在REPL环境工作很好,返回String类型的结果。当你过渡到Gremlin应用程序,理解如何明确的执行遍历很重要,因为不会自动的执行。下面是常用的方法来执行遍历:

下面是一端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
上一篇下一篇

猜你喜欢

热点阅读