Amazon Neptune学习笔记

Gremlin

Neptune Gremlin 实施的不同之处

Pre-Bound 变量

遍历对象 g 是 Pre-bound。不支持 graph 对象

TinkerPop 枚举

Neptune 不支持枚举值的完全限定类名称。例如,您在 Groovy 请求中必须使用 single,不能使用 org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality.single。

  • 枚举类型由参数类型决定。
  • 下表显示了允许的枚举值和相关的 TinkerPop 完全限定名称。
    在这里插入图片描述

Java 代码

**Neptune 不支持调用由支持的 Gremlin API 以外的任意 Java 或 Java 库调用定义的方法。**例如,不允许 java.lang.*、Date() 和 g.V().tryNext().orElseGet()。

日期和时间

Neptune 提供了 datetime 方法,用于为 Gremlin Groovy 变体中发送的查询指定日期和时间。这包括 Gremlin 控制台、使用 HTTP REST API 的文本字符串以及使用 Groovy 的任何其他序列化。日期和时间值必须使用 datetime() 函数进行指定。

  • 注意:这仅适用于您将 Gremlin 查询作为文本字符串 发送的方法。如果您使用的是 Gremlin 语言变体 (GLV),则必须使用该语言的本机日期类和函数。
  • datetime( ) 函数采用符合 ISO-8601 日期时间的字符串值,最高精度为毫秒。例如:datetime(‘2018-01-01T00:00:00’)
  • ISO-8601 日期时间格式的一些示例如下所示:
YYYY-MM-DD
YYYY-MM-DDTHH:mm
YYYY-MM-DDTHH:mm:SS
YYYY-MM-DDTHH:mm:SS.ssss
YYYY-MM-DDTHH:mm:SSZ

脚本执行

所有查询必须以遍历对象 g 开头。
多个遍历可由分号 (😉 或换行符 (\n) 分隔发布。最后一个以外的每个语句都必须以要执行的 next() 步骤结尾。仅返回最后遍历数据。

会话

Neptune 属于无会话型。它不支持控制台 session 参数。

事务

Neptune 在每个 Gremlin 遍历开始时打开新的事务,并在遍历成功完成后结束事务。事务会在出现错误时回滚。
用分号 (😉 或换行符 (\n) 分隔的多个语句包含在单个事务中。最后一个以外的每个语句都必须以要执行的 next() 步骤结尾。仅返回最后遍历数据。
不支持使用 tx.commit() 和 tx.rollback() 的手动事务逻辑。

顶点和边缘 ID

Neptune Gremlin 顶点和边缘 ID 必须属于 String 类型。如果您在添加顶点或边缘时未提供 ID,则 UUID 会生成并转换为一个字符串;例如,“48af8178-50ce-971a-fc41-8c9a954cea62”。

  • 注意:这表示用户提供的 ID 受支持,但它们在正常使用中是可选的。但是,Neptune Load 命令要求所有 ID 使用 ~id 字段采用 Neptune CSV 格式进行指定。

用户提供的 ID

用户提供的 ID 在 Neptune Gremlin 中允许,且具有以下规定。

* 提供的 ID 是可选的。
* 仅支持顶点和边缘。
* 仅支持 String 类型。

要使用自定义 ID 创建新顶点,请将 property 步骤与 id 关键字一起使用:g.addV().property(id, ‘customid’)。

  • 注意:请勿为 id 关键字加上引号。
  • 所有顶点 ID 必须是唯一的,并且所有边缘 ID 也必须是唯一的。但是,Neptune 允许顶点和边缘具有相同的 ID。
  • 如果您尝试使用 g.addV() 创建新顶点并且已存在具有该 ID 的顶点,则此操作将失败。此情况的例外是,如果为顶点指定新标签,该操作将成功,但会将新标签和指定的任何其他属性添加到现有顶点。不会覆盖任何内容。未创建新顶点。顶点 ID 不会更改并会保持唯一。
    例如,以下 Gremlin 控制台命令将成功:
gremlin> g.addV('label1').property(id, 'customid')
gremlin> g.addV('label2').property(id, 'customid')
gremlin> g.V('customid').label()
==>label1::label2

顶点属性 ID

顶点属性 ID 会自动生成且可以在查询时显示为正数或负数。

顶点属性的基数

Neptune 支持集基数和单一基数。如果未指定,则集基数处于选中状态。这意味着,如果您设置一个属性值,它会向该属性添加新值,但是仅当它未显示在一组值中时。这是 Set 的 Gremlin 枚举值。
不支持 List。有关属性基数的更多信息,请参阅 Gremlin JavaDoc 中的顶点主题。

更新顶点属性

要更新属性值而无需向一组值添加其他值,请在 property 步骤中指定 single 基数。

g.V('exampleid01').property(single, 'age', 25)
  • 注意:这将删除该属性的所有现有值。

标签

Neptune 支持一个顶点的多个标签。创建标签时,您可以指定多个标签,同时使用 :: 分隔它们。例如,g.addV(“Label1::Label2::Label3”) 添加具有三个不同标签的顶点。hasLabel 步骤与具有以下任一三个标签的此顶点相匹配:hasLabel(“Label1”)、hasLabel(“Label2”) 和 hasLabel(“Label3”)。

  • 注意::: 分隔符仅用于此用途。您不能在 hasLabel 步骤中指定多个标签。例如,hasLabel(“Label1::Label2”) 与任何内容都不匹配。

变量

Neptune 不支持 Gremlin 变量且不支持 bindings 属性

超时

Gremlin 控制台命令 :remote config timeout 仅设置本地超时。要为 Neptune 设置远程查询超过,请使用 neptune_query_timeout 参数。

转义字符

Neptune 解析所有转义字符,如 Apache Groovy 语言文档的转义特殊字符部分中所述。

Groovy 限制

Neptune 不支持不以 g 开头的 Groovy 命令。这包括数学(例如:1+1)、系统调用(例如:System.nanoTime())和变量定义(例如:1+1)。

  • 注意:Neptune 不支持完全限定类名称。例如,您在 Groovy 请求中必须使用 single,不能使用 org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality.single。

序列化

Neptune 根据请求的 MIME 类型支持以下串行化。
在这里插入图片描述

Lambda 步骤

Neptune 不支持 Lambda 步骤。

不支持的 Gremlin 方法

Neptune 不支持以下 Gremlin 方法:

  • org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal.program
    (org.apache.tinkerpop.gremlin.process.cmputer.VertexProgram)
  • org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal.sideEffect
    (java.util.function.Consumer)
  • org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal.from
    (org.apache.tinkerpop.gremlin.structure.Vertex)
  • org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal.to
    (org.apache.tinkerpop.gremlin.structure.Vertex)
    例如,不允许以下遍历:g.V().addE(‘something’).from(g.V().next()).to(g.V().next())。

不支持的 Gremlin 步骤

Neptune 不支持以下 Gremlin 步骤:

其他功能

Gremlin 的 Neptune 实施不公开 graph 对象。以下部分介绍支持和不支持的 graph 功能。

  • Neptune 中不支持 Gremlin io( ) 步骤。例如,g.io(“graph.xml”).read().iterate() 查询不可用于 Neptune。

Gremlin 图形支持的功能

参考:https://docs.aws.amazon.com/zh_cn/neptune/latest/userguide/access-graph-gremlin-differences.html?shortFooter=true

Gremlin控制台

  • 参考:https://docs.aws.amazon.com/zh_cn/neptune/latest/userguide/access-graph-gremlin-console.html?shortFooter=true

下载安装

wget https://archive.apache.org/dist/tinkerpop/3.3.2/apache-tinkerpop-gremlin-console-3.3.2-bin.zip
unzip apache-tinkerpop-gremlin-console-3.3.2-bin.zip
cd apache-tinkerpop-gremlin-console-3.3.2

修改配置

  • 在提取的目录的 conf 子目录中,创建名为 neptune-remote.yaml 的包含以下文本的文件。将 your-neptune-endpoint 替换为您的 Neptune 数据库实例的主机名或 IP 地址。方括号 ([ ]) 是必需的。
hosts: [your-neptune-endpoint]
port: 8182
serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}

操作

  • 在终端中,导航到 Gremlin 控制台目录 (apache-tinkerpop-gremlin-console-3.3.2),然后输入以下命令来运行 Gremlin 控制台。
bin/gremlin.sh  
  • 您应看到以下输出:
         \,,,/
         (o o)
-----oOOo-(3)-oOOo-----
plugin activated: tinkerpop.server
plugin activated: tinkerpop.utilities
plugin activated: tinkerpop.tinkergraph
gremlin> 
  • 在 gremlin> 提示符处,输入以下命令以连接到 Neptune 数据库实例。
:remote connect tinkerpop.server conf/neptune-remote.yaml
  • 在 gremlin> 提示符处,输入以下命令以切换到远程模式。这会将所有 Gremlin 查询发送到远程连接。
:remote console
  • 输入以下命令以将查询发送到 Gremlin 图形。
g.V().limit(1)
  • 完成后,输入以下命令以退出 Gremlin 控制台。
:exit
  • 注意
* 使用分号 (;) 或换行符 (\n) 分隔每个语句。
* 在最后遍历之前的每个遍历必须以要执行的 next() 结尾。仅返回最后遍历中的数据。

演练

  • 添加带有标签和属性的顶点
gremlin> g.addV('person').property('name', 'justin')
==>v[30b583c5-acf9-31aa-eee7-99c1644e3367]
// 顶点分配有包含 GUID 的 string ID。Neptune 中的所有顶点 ID 均为字符串。
  • 添加具有自定义 ID 的顶点
gremlin> g.addV('person').property(id, '1').property('name', 'martin')
==>v[1]
// id 属性未使用引号引起来。这是顶点 ID 的关键字。顶点 ID 具有一个字符串,其中包含数字 1。
// 普通属性名称必须包含在引号中。
  • 更改属性或添加属性(如果属性不存在)
gremlin> g.V('1').property(single, 'name', 'marko')
==>v[1]
// 此处介绍如何更改上一步中顶点的 name 属性。这会从 name 属性删除现有值。
// 如果您未指定 single,则会改为将值附加到 name 属性(如果尚未附加)。
  • 添加属性,但在属性已有值时附加属性
gremlin> g.V('1').property('age', 29)
==>v[1]如果 age 属性已有值,此命令将 29 附加到属性。例如,如果 age 属性是 27,则新值将为 [ 27, 29 ]// Neptune 使用集基数作为默认操作。
// 此命令添加值为 29 的 age 属性,但不替换任何现有值。
// 如果 age 属性已有值,此命令将 29 附加到属性。例如,如果 age 属性是 27,则新值将为 [ 27, 29 ]。
  • 添加多个顶点
gremlin> g.addV('person').property(id, '2').property('name', 'vadas').property('age', 27).next()
==>v[2]
gremlin> g.addV('software').property(id, '3').property('name', 'lop').property('lang', 'java').next()
==>v[3]
gremlin> g.addV('person').property(id, '4').property('name', 'josh').property('age', 32).next()
==>v[4]
gremlin> g.addV('software').property(id, '5').property('name', 'ripple').property('ripple', 'java').next()
==>v[5]
gremlin> g.addV('person').property(id, '6').property('name', 'peter').property('age', 35)
==>v[6]
// 可以同时将多个语句发送到 Neptune。
// 语句可以使用换行符 ('\n')、空格 (' ')、分号 ('; ') 或什么都不使用(例如,g.addV(‘person’).next()g.V() 是有效的)来分隔。
// 注意
// Gremlin 控制台对每个换行符 ('\n') 发送单独的命令,因此在该例中,它们将成为单独的事务处理。此示例的每个命令位于单独一行中,以便阅读。删除换行符 ('\n') 可以将其通过 Gremlin 控制台作为单个命令发送。
// 除了最后一条语句之外的所有语句必须以终止步骤结尾,例如 .next() 或 .iterate(),否则语句不会运行。Gremlin 控制台不需要这些终止步骤。
// 一起发送的所有语句包括在单个事务处理中,并且一起成功或失败。
  • 添加边
gremlin> g.V('1').addE('knows').to(g.V('2')).property('weight', 0.5).next()
==>e[fab583cd-5686-b3df-60f8-ab792ca96ba9][1-knows->2]
gremlin> g.addE('knows').from(g.V('1')).to(g.V('4')).property('weight', 1.0) 
==>e[60b583cd-74fe-581d-f3b2-637328927188][1-knows->4]
// 这里介绍了两种不同的方法来添加边缘。
  • 添加现代图形的其余部分
gremlin> g.V('1').addE('created').to(g.V('3')).property('weight', 0.4).next()
==>e[c4b583cd-06e0-9740-98a0-15f0ed923186][1-created->3]
gremlin> g.V('4').addE('created').to(g.V('5')).property('weight', 1.0).next()
==>e[7eb583cd-0793-821a-2466-78eba1efa94e][4-created->5]
gremlin> g.V('4').addE('knows').to(g.V('3')).property('weight', 0.4).next()
==>e[7ab583cd-083a-1491-a623-f7102b950e85][4-knows->3]
gremlin> g.V('6').addE('created').to(g.V('3')).property('weight', 0.2)
==>e[cab583cd-08e4-f637-944f-810fb09bda56][6-created->3]
  • 删除顶点
gremlin> g.V().has('name', 'justin').drop()
gremlin> 
// 删除 name 属性等于 justin 的顶点。
// 注意:到这里,您拥有了完整的 Apache TinkerPop 现代图形。TinkerPop 文档的“遍历”部分中的示例使用现代图形。
  • 运行遍历
gremlin> g.V().hasLabel('person')
==>v[2]
==>v[6]
==>v[1]
==>v[4]
// 返回所有 person 顶点。
  • 使用值运行遍历 (valueMap())
gremlin> g.V().has('name', 'marko').out('knows').valueMap()
==>{name=[vadas], age=[27]}
==>{name=[josh], age=[32]}
// 返回 marko“知道”的所有顶点的键值对。
  • 指定多个标签
gremlin> g.addV("Label1::Label2::Label3") 
==>v[54b583d3-f0a3-f0ce-2ddb-3e92a968744b]
// Neptune 支持一个顶点的多个标签。创建标签时,您可以指定多个标签,同时使用 :: 分隔它们。
// 此示例添加具有三个不同标签的顶点。
// hasLabel 步骤与具有以下任一三个标签的此顶点相匹配:hasLabel("Label1")、hasLabel("Label2") 和 hasLabel("Label3")。
// :: 分隔符仅用于此用途。
// 您不能在 hasLabel 步骤中指定多个标签。例如,hasLabel("Label1::Label2") 与任何内容都不匹配。
  • 指定时间/日期
gremlin> g.V().property(single, 'lastUpdate', datetime('2018-01-01T00:00:00'))
==>v[2]
==>v[6]
==>v[54b583d3-f0a3-f0ce-2ddb-3e92a968744b]
==>v[1]
==>v[3]
==>v[4]
==>v[5]
// Neptune 不支持 Java 日期。改用 datetime() 函数。datetime() 接受符合 ISO8061 的 datetime 字符串。
// 它支持以下格式:YYYY-MM-DD、YYYY-MM-DDTHH:mm、YYYY-MM-DDTHH:mm:SS、YYYY-MM-DDTHH:mm:SSZ
  • 删除顶点、属性或边
gremlin> g.V().hasLabel('person').properties('age').drop().iterate()
gremlin> g.V('1').drop().iterate()
gremlin> g.V().outE().hasLabel('created').drop()
gremlin>
// 注意 .next() 步骤不可与 .drop() 一起使用。请改用 .iterate()

完成后,键入以下命令以退出 Gremlin 控制台。

gremlin> :exit

Gremlin常用语法总结

Gremlin是 Apache TinkerPop 框架下的图遍历语言。Gremlin是一种函数式数据流语言,可以使得用户使用简洁的方式表述复杂的属性图(property graph)的遍历或查询。每个Gremlin遍历由一系列步骤(可能存在嵌套)组成,每一步都在数据流(data stream)上执行一个原子操作。

基本操作

Gremlin 语言包括三个基本的操作:

  • map-step:对数据流中的对象进行转换;
  • filter-step:对数据流中的对象就行过滤;
  • sideEffect-step:对数据流进行计算统计;

核心概念

  • Graph: 维护节点&边的集合,提供访问底层数据库功能,如事务功能。
  • Element: 维护属性集合,和一个字符串label,表明这个element种类。
  • Vertex: 继承自Element,维护了一组入度,出度的边集合。
  • Edge: 继承自Element,维护一组入度,出度vertex节点集合。
  • Property: kv键值对。
  • VertexProperty: 节点的属性,有一组健值对kv,还有额外的properties 集合。同时也继承自element,必须有自己的id, label。
  • Cardinality: 【single, list, set】 节点属性对应的value是单值,还是列表,或者set。

Gremlin 查询示例

  • 准备:
gremlin> g.addV('person').property(id,'1').property('name','tom')
==>v[1]
gremlin> g.addV('person').property(id,'2').property('name','jack')
==>v[2]
gremlin> g.addV('software').property(id,'3').property('lang','java')
==>v[3]
gremlin> g.addE('uses').from(g.V('1')).to(g.V('3'))
==>e[8ab5866d-4a04-20cf-e4f4-610ec1b45a84][1-uses->3]
gremlin> g.addE('develops').from(g.V('2')).to(g.V('3'))
==>e[96b5866d-74b3-4980-b2b2-93abe93ab990][2-develops->3]
gremlin> g.addE('knows').from(g.V('1')).to(g.V('2'))
==>e[76b5866d-917c-c238-e37d-2ee823b897c2][1-knows->2]

在这里插入图片描述

* 顶点:
	person
	software
* 边:
	uses(person -> software)
	develops(person -> software)
	knows(person -> person)
查询点
// 查询所有点,但限制点的返回数量为100,也可以使用range(x, y)的算子,返回区间内的点数量。
gremlin> g.V().limit(100)
==>v[2]
==>v[1]
==>v[3]
// 查询点的label值为'software'的点。
gremlin> g.V().hasLabel('software')
==>v[3]
// 查询id为‘1’的点。
gremlin> g.V('1')
==>v[1]
查询边
// 查询所有边,不推荐使用,边数过大时,这种查询方式不合理,一般需要添加过滤条件或限制返回数量。
gremlin> g.E() 
==>e[96b5866d-74b3-4980-b2b2-93abe93ab990][2-develops->3]
==>e[76b5866d-917c-c238-e37d-2ee823b897c2][1-knows->2]
==>e[8ab5866d-4a04-20cf-e4f4-610ec1b45a84][1-uses->3]
// 查询边id为‘96b5866d-74b3-4980-b2b2-93abe93ab990’的边。
gremlin> g.E('96b5866d-74b3-4980-b2b2-93abe93ab990')
==>e[96b5866d-74b3-4980-b2b2-93abe93ab990][2-develops->3]
// 查询label为‘develops’的边。
gremlin> g.E().hasLabel('develops') 
==>e[96b5866d-74b3-4980-b2b2-93abe93ab990][2-develops->3]
// 查询点id为‘2’所有label为‘develops’的边。
gremlin> g.V('2').outE('develops') 
==>e[96b5866d-74b3-4980-b2b2-93abe93ab990][2-develops->3]
查询属性
// 查询点的所有属性(可填参数,表示只查询该点, 一个点所有属性一行结果)。
gremlin> g.V().limit(3).valueMap() 
==>{name=[jack]}
==>{name=[tom]}
==>{lang=[java]}
// 查询点的label。
gremlin> g.V().limit(1).label() 
==>person
// 查询点的name属性(可不填参数,表示查询所有属性, 一个点每个属性一行结果,只有value,没有key)。
gremlin> g.V().limit(10).values('name') 
==>jack
==>tom
新增点
//新增点,Label为user,ID为500,age为18-24。
Graph graph = TinkerGraph.open();
graph.addVertex(label,'person',id,'500','age','18-24') 
  • neptune支持方式
//新增点,Label为user,ID为500,age为18。
gremlin> g.addV('person').property(id,'500').property('age','18') 
==>v[500]
新增边
a = graph.addVertex(label,'person',id,'501','age','18-24')
b = graph.addVertex(label,'software',id,'502','title','love')
// 新增边,边的两个点ID分别为501、502。
a.addEdge('develops', b, 'Year','1994') 
  • neptune支持方式:neptune暂不支持变量
g.addV('person').property(id,'501').property('age', 24)
g.addV('software').property(id,'502').property('title', 'love')
g.V('501').addE('develops').to(g.V('502')).property('Year', '1994')
删除点
// 删除ID为600的点。
g.V('600').drop() 
删除边
// 删除ID为“501-502-0”的边。
g.E('501-502-0').drop() 

Gremlin语法特性

  • 数据准备:
// 添加顶点
gremlin> g.addV('person').property(id, '1').property('name', 'marko').property('age', 29)
==>v[1]
gremlin> g.addV('person').property(id, '2').property('name', 'vadas').property('age', 27)
==>v[2]
gremlin> g.addV('software').property(id, '3').property('name', 'lop').property('lang', 'java')
==>v[3]
gremlin> g.addV('person').property(id, '4').property('name', 'josh').property('age', 32)
==>v[4]
gremlin> g.addV('software').property(id, '5').property('name', 'ripple').property('lang', 'java')
==>v[5]
gremlin> g.addV('person').property(id, '6').property('name', 'peter').property('age', 35)
==>v[6]
// 添加边
gremlin> g.addE('knows').from(g.V('1')).to(g.V('2')).property(id, '7').property('weight', 0.5)
==>e[7][1-knows->2]
gremlin> g.addE('knows').from(g.V('1')).to(g.V('4')).property(id, '8').property('weight', 1.0)
==>e[8][1-knows->4]
gremlin> g.addE('created').from(g.V('1')).to(g.V('3')).property(id, '9').property('weight', 0.4)
==>e[9][1-created->3]
gremlin> g.addE('created').from(g.V('4')).to(g.V('5')).property(id, '10').property('weight', 1.0)
==>e[10][4-created->5]
gremlin> g.addE('created').from(g.V('4')).to(g.V('3')).property(id, '11').property('weight', 0.4)
==>e[11][4-created->3]
gremlin> g.addE('created').from(g.V('6')).to(g.V('3')).property(id, '12').property('weight', 0.2)
==>e[12][6-created->3]

在这里插入图片描述

基础
  • V():查询顶点,一般作为图查询的第1步,后面可以续接的语句种类繁多。例,g.V(),g.V(‘v_id’),查询所有点和特定点。
  • E():查询边,一般作为图查询的第1步,后面可以续接的语句种类繁多。
  • id():获取顶点、边的id。例:g.V().id(),查询所有顶点的id。
  • label():获取顶点、边的 label。例:g.V().label(),可查询所有顶点的label。
  • key() / value():获取属性的key/value的值。
  • properties():获取顶点、边的属性;可以和 key()、value()搭配使用,以获取属性的名称或值。例:g.V().properties(‘name’),查询所有顶点的 name 属性。例如:g.V().properties().key()、g.V().properties().value()
  • valueMap():获取顶点、边的属性,以Map的形式体现,和properties()比较像。
  • values():获取顶点、边的属性值。例,g.V().values() 等于 g.V().properties().value()。
遍历

顶点为基准:

  • out(label):根据指定的 Edge Label 来访问顶点的 OUT 方向邻接(可以是零个 Edge Label,代表所有类型边;也可以一个或多个 Edge Label,代表任意给定 Edge Label 的边,下同)。
  • in(label):根据指定的 Edge Label 来访问顶点的 IN 方向邻接
  • both(label):根据指定的 Edge Label 来访问顶点的双向邻接
  • outE(label):根据指定的 Edge Label 来访问顶点的 OUT 方向邻接
  • inE(label):根据指定的 Edge Label 来访问顶点的 IN 方向邻接
  • bothE(label):根据指定的 Edge Label 来访问顶点的双向邻接
    边为基准的:
  • outV():访问边的出顶,出顶点是指边的起始顶点。
  • inV():访问边的入顶,入顶点是指边的目标顶点,也就是箭头指向的顶点。
  • bothV():访问边的双向顶
  • otherV():访问边的伙伴顶点,即相对于基准顶点而言的另一端的顶点。
过滤

在众多Gremlin的语句中,有一大类是filter类型,顾名思义,就是对输入的对象进行条件判断,只有满足过滤条件的对象才可以通过filter进入下一步。

has

has语句是filter类型语句的代表,能够以顶点和边的属性作为过滤条件,决定哪些对象可以通过。常用的有下面几种:

  • has(key,value):通过属性的名字和值来过滤顶点或边。
  • has(label, key, value):通过label、属性的名字和值过滤顶点和边。
  • has(key,predicate):通过对指定属性用条件过滤顶点和边,例:g.V().has(‘age’, gt(20)),可得到年龄大于20的顶点。
  • hasLabel(labels…​):通过 label 来过滤顶点或边,满足label列表中一个即可通过。
  • hasId(ids…​):通过 id 来过滤顶点或者边,满足id列表中的一个即可通过。
  • hasKey(keys…​):通过 properties 中的若干 key 过滤顶点或边。
  • hasValue(values…​):通过 properties 中的若干 value 过滤顶点或边。
  • has(key):properties 中存在 key 这个属性则通过,等价于hasKey(key)。
  • hasNot(key): 和 has(key) 相反。

例子:

// lable 等于 person 的所有顶点
g.V().hasLabel('person')
// 所有年龄在20(含)~30(不含)之间的顶点
g.V().has('age',inside(20,30)).values('age') 
// 所有年龄不在20(含)~30(不含)之间的顶点
g.V().has('age',outside(20,30)).values('age') 
// name 是'josh'或'marko'的顶点的属性
g.V().has('name',within('josh','marko')).valueMap() 
// name 不是'josh'或'marko'的顶点的属性
g.V().has('name',without('josh','marko')).valueMap() 
// 同上
g.V().has('name',not(within('josh','marko'))).valueMap() g.V().hasNot('age').values('name') 
// age 这个属性的所有 value
g.V().properties().hasKey('age').value() 
// 不含 age 这个属性的所有 顶点的 name 属性
g.V().hasNot('age').values('name') 
路径
  • 在使用Gremlin对图进行分析时,关注点有时并不仅仅在最终达到顶点、边或者属性,通过什么样的路径到达最终的顶点、边和属性同样重要。此时可以借助path() 来获取经过的路径信息。
  • path() 返回当前遍历过的所有路径。有时需要对路径进行过滤,只选择没有环路的路径或者选择包含环路的路径,Gremlin 针对这种需求提供了两种过滤路径的step:simplePath() 和cyclicPath()。
path():获取当前遍历过的所有路径;
simplePath():过滤掉路径中含有环路的对象,只保留路径中不含有环路的对象;
cyclicPath():过滤掉路径中不含有环路的对象,只保留路径中含有环路的对象。
  • 例子
// 寻找4跳以内从 andy 到 jack 的最短路径
g.V("andy").repeat(both().simplePath()).until(hasId("target_v_id").and().loops().is(lte(4))).hasId("jack").path().limit(1)
// “Titan” 顶点到与其有两层关系的顶点的不含环路的路径(只包含顶点)
g.V().hasLabel('software').has('name','Titan').both().both().simplePath().path()
迭代
  • repeat():指定要重复执行的语句。
  • times(): 指定要重复执行的次数,如执行3次。
  • until():指定循环终止的条件,如一直找到某个名字的朋友为止。
  • emit():指定循环语句的执行过程中收集数据的条件,每一步的结果只要符合条件则被收集,不指定条件时收集所有结果。
  • loops():当前循环的次数,可用于控制最大循环次数等,如最多执行3次。
* repeat() 和 until() 的位置不同,决定了不同的循环效果:
	repeat() + until():等同 do-while;
	until() + repeat():等同 while-do。
	
* repeat() 和 emit() 的位置不同,决定了不同的循环效果:
	repeat() + emit():先执行后收集;
	emit() + repeat():表示先收集再执行。

注意:
emit()与times()搭配使用时,是“或”的关系而不是“与”的关系,满足两者间任意一个即可。
emit()与until()搭配使用时,是“或”的关系而不是“与”的关系,满足两者间任意一个即可。

  • 例1:根据出边进行遍历,直到抵达叶子节点(无出边的顶点),输出其路径顶点名
g.V('1').repeat(out()).until(outE().count().is('0')).path().by('name')
  • 例2:查询顶点’1’的’3’度 OUT 可达点路径
g.V('1').repeat(out()).until(loops().is('3')).path()
转换
  • map():可以接受一个遍历器 Step 或 Lamda 表达式,将遍历器中的元素映射(转换)成另一个类型的某个对象(一对一),以便进行下一步处理。
  • flatMap():可以接受一个遍历器 Step 或 Lamda 表达式,将遍历器中的元素映射(转换)成另一个类型的某个对象流或迭代器(一对多)。
  • 例子:
// 创建了 titan 的作者节点的姓名
g.V('titan').in('created').map(values('name'))
// 创建了 titan 的作者节点的所有出边
g.V('titan').in('created').flatMap(outE())
排序
  • order()
  • order().by()
// 默认升序排列
g.V().values('name').order()
// 按照元素属性age的值升序排列,并只输出姓名
g.V().hasLabel('person').order().by('age', asc).values('name')
逻辑
  • is():可以接受一个对象(能判断相等)或一个判断语句(如:P.gt()、P.lt()、P.inside()等),当接受的是对象时,原遍历器中的元素必须与对象相等才会保留;当接受的是判断语句时,原遍历器中的元素满足判断才会保留,其实接受一个对象相当于P.eq()。
  • and():可以接受任意数量的遍历器(traversal),原遍历器中的元素,只有在每个新遍历器中都能生成至少一个输出的情况下才会保留,相当于过滤器组合的与条件。
  • or():可以接受任意数量的遍历器(traversal),原遍历器中的元素,只要在全部新遍历器中能生成至少一个输出的情况下就会保留,相当于过滤器组合的或条件。
  • not():仅能接受一个遍历器(traversal),原遍历器中的元素,在新遍历器中能生成输出时会被移除,不能生成输出时则会保留,相当于过滤器的非条件。
  • 例1:
// 筛选出顶点属性“age”等于28的属性值,与`is(P.eq(28))`等效
g.V().values('age').is(28)
// 所有包含出边“supports”和“created”的顶点的名字“name”
g.V().and(outE('supports'), outE('created')).values('name')
// 使用 where语句 实现上面的功能
g.V().where(outE('supports').and().outE('created').values('name')
// 筛选出所有不是“person”的顶点的“label”
g.V().not(hasLabel('person')).label()
  • 例2:获取所有最多只有一条“created”边并且年龄不等于28的“person”顶点
gremlin> g.V().hasLabel('person').and(outE('created').count().is(lte(1)), values("age").is(P.not(P.eq(28)))).values('name')
==>vadas
==>peter
==>marko
统计
  • sum():将 traversal 中的所有的数字求和。
  • max():对 traversal 中的所有的数字求最大值。
  • min():对 traversal 中的所有的数字求最小值。
  • mean():将 traversal 中的所有的数字求均值。
  • count():统计 traversal 中 item 总数。
  • 例子:
// 计算所有“person”的“created”出边数的均值
g.V().hasLabel('person').map(outE('created').count()).mean()
分支
  • choose():分支选择, 常用使用场景为: choose(predicate, true-traversal, false-traversal),根据 predicate 判断,当前对象满足时,继续 true-traversal,否则继续 false-traversal。
  • optional():类似于 by() 无实际意义,搭配 choose() 使用。
  • 例1:if-else
gremlin> g.V().hasLabel('person').choose(values('age').is(lte(30)),__.in(),__.out()).values('name')
==>marko
==>lop
==>lop
==>ripple
// 结果分析:g.V().hasLabel('person').values('age').is(lte(30)) 的结果是27,29
// 所以 true-traversal——【27,29】:__in()求入度,age=27的入度顶点name是marko,age=29的入度顶点没有
// false-traversal——【32,35】:__out()求出度,age=35的出度顶点name为lop,age=32的出度顶点name为lop和ripple
  • 例2:if-elseif-else
// 查找所有的“person”类型的顶点
// 如果“age”属性等于0,输出名字
// 如果“age”属性等于28,输出年龄
// 如果“age”属性等于29,输出他开发的软件的名字
// choose(predicate).option().option()...
gremlin>  g.V().hasLabel('person').choose(values('age')).option(0, values('name')).option(28, values('age')).option(29, __.out('created').values('lang'))
==>java
//
gremlin> g.V().hasLabel('person').choose(values('age')).option(0, values('name')).option(28, values('age')).option(29, __.out('created').values('name')).option(none, values('name'))
==>vadas
==>peter
==>lop
==>josh

Neptune可视化工具范例.jpg(在这里输入文件名)

在这里插入图片描述
基于 github 的一个开源项目 graphexp 实现 Neptune 图数据库可视化。
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

讲文明的喜羊羊拒绝pua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值