Chapter 6. Gremlin Query Language (Gremlin 查询语言)

Gremlin 是 JanusGraph 的查询语言,用于从图中检索数据和修改数据。 Gremlin 是一种面向路径的语言,它简洁地表达了复杂的图形遍历和变异操作。 Gremlin 是一种函数式语言,遍历运算符被链接在一起形成类似路径的表达式。 例如,“来自 Hercules,横穿他的父亲,然后他的父亲的父亲,并返回祖父的名字。”。

Gremlin 是 Apache TinkerPop 的一个组件。 它独立于 JanusGraph 开发,并得到大多数图形数据库的支持。 通过 Gremlin 查询语言在 JanusGraph 之上构建应用程序,用户可以避免供应商限制,因为他们的应用程序可以迁移到支持 Gremlin 的其他图形数据库。

本节是 Gremlin 查询语言的简要概述。 有关 Gremlin 的更多信息,请参阅以下资源:

6.1 介绍遍历

Gremlin 查询是从左到右计算的一系列操作/函数。 下面通过第3章“入门”中讨论的 Gods 数据集图表提供了一个简单的祖父查询。(译著:参见翻译 JanusGraph 入门指南

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 顶点(即 Jupiter)。
  6. 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

对于一个合理的查询,通常可以查看每个返回的属性,而不是分配的长 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

请注意显示 Hercules 的整个父系树分支的相关遍历。 提供这种更复杂的遍历以展示语言的灵活性和表达性。 对 Gremlin 的有效掌控为 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}

每个步骤(由分隔表示)是对上一步骤返回的对象进行操作的函数。Gremlin 语言中有许多步骤(参见 Gremlin Steps)。通过简单地改变步骤的步长或顺序,可以实现不同的遍历语义。下面的例子返回所有与 Hercules 共同战斗过的相同怪物的人的名字,他们本身不是赫拉克勒斯。即 "co-battlers" 或者 "allies"。

鉴于神的图形只有一个战斗者(Hercules),另一个战斗者(为了举例)被添加到图形中,Gremlin 展示了如何将顶点和边添加到图形中。

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

添加顶点时,可以提供可选的顶点标签。 添加边时必须指定边标签。 可以在顶点和边上设置作为属性的键值对。 使用 SETLIST 基数定义属性键时,必须在向顶点添加相应属性时使用 addProperty

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

上面的例子有4个链接函数:outinexceptvalues(即 name 是 values('name') 的简写)。 每个的函数签名在下面逐条列出,其中 V 是顶点而 U 是任何对象,其中 V 是 U 的子集。

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

将函数链接在一起时,传入类型必须与传出类型匹配,其中U匹配任何内容。 因此,上面的 "co-battled/ally" 遍历是正确的。

注意:本节中介绍的 Gremlin 概述重点介绍了 Gremlin 控制台中使用 Gremlin-Groovy 语言的实现。 可以使用 Gremlin 的其他语言驱动语言变体

6.2 迭代遍历

Gremlin 控制台的一个便捷功能是它会自动迭代从 gremlin> 提示符执行的查询的所有结果。这在 REPL 环境中运行良好,它将结果显示为 String。当您转向编写 Gremlin 应用程序时,了解如何显式迭代遍历非常重要,因为应用程序的遍历不会自动迭代。以下是迭代 Traversal 的一些常用方法:

  • iterate() - 没有返回结果,或可以忽略
  • next() - 可以获取一个返回结果,请确保先使用 hasNext()
  • next(int n) - 获得接下来的 n 个结果,请确保先使用 hasNext()
  • toList() - 以列表形式获取所有结果。 如果没有结果,则返回空列表。

下面显示了一个 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

翻译自官方文档原文地址:Chapter 6. Gremlin Query Language

如果觉得这对你有用,请随意赞赏,给与作者支持
评论 0
最新评论