当前位置: 首页 > 工具软件 > Gremlin > 使用案例 >

Gremlin 查询语言

司徒宏远
2023-12-01

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

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

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

除了这些资源之外,连接到 JanusGraph 还解释了如何在不同的编程语言中使用 Gremlin 来查询 JanusGraph 服务器。

介绍性遍历

Gremlin 查询是从左到右计算的一系列操作/函数。下面提供了对入门中讨论的 Gods数据集图形的简单祖父查询。

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 遍历传出的父亲边缘。
  5. 'out('father')`:从 Hercules 的父亲的顶点(即木星)遍历出父亲边缘。
  6. name: 获取“hercules”顶点祖父的 name 属性。

综合起来,这些步骤形成了一个类似路径的遍历查询。每个步骤都可以分解并展示其结果。这种构建遍历/查询的风格在构建更大、更复杂的查询链时很有用。

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 步骤)。通过简单地改变一个步骤或步骤的顺序,不同的遍历语义被制定。下面的例子返回了所有与 Hercules 相同的怪物战斗过的人的名字,这些怪物本身不是 Hercules(即“co-battlers”或“盟友”)。

鉴于The Graph of the Gods只有一个战士 (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

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

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

上面的例子有 4 个链式函数:outinexcept、 和 values(即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-batted/ally”遍历是正确的。

笔记

本节中介绍的 Gremlin 概述侧重于 Gremlin 控制台中使用的 Gremlin-Groovy 语言实现。有关使用 Groovy 以外的其他语言和独立于 Gremlin 控制台连接到 JanusGraph的信息,请参阅连接到 JanusGraph

迭代遍历

Gremlin 控制台的一项便利功能是它会自动迭代从 gremlin> 提示符执行的查询的所有结果。这在REPL环境中运行良好,因为它将结果显示为字符串。当您过渡到编写 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

 类似资料: