TinkerPop中的遍历:图的遍历策略
遍历策略
一个TraversalStrategy分析一个遍历,如果遍历符合它的标准,可以相应地改变它。遍历策略在编译时被执行,并构成Gremlin遍历机的编译器的基础。有五类策略分列如下:
- decoration: 在应用程序级别的特性可以嵌入到遍历逻辑中
- optimization: 在TinkerPop3级别有更高效的方式来表达遍历
- provider optimization: 在图的系统/语言/驱动程序级别上有一种更有效的方式来表示遍历
- finalization: 执行遍历之前需要进行一些最终的调整/清理/分析
- verification: 某些遍历对于应用程序或遍历引擎是不合法的
Note
explain()步骤向用户显示每个注册策略如何改变遍历。
如:gremlin> g.V().has('name','marko').explain()
元素ID策略
ElementIdStrategy提供对元素标识符的控制。一些Graph实现(如TinkerGraph)允许在创建元素时指定自定义标识符:
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> v = g.addV().property(id,'42a').next()
==>v[42a]
gremlin> g.V('42a')
==>v[42a]
来源: http://tinkerpop.apache.org/docs/3.2.6/reference/#traversalstrategy
其他Graph实现(如Neo4j)会自动生成元素标识符,并且不能分配。作为一个帮手,可以使用ElementIdStrategy通过使用顶点和边索引来使标识符赋值成为可能。
如:
gremlin> graph = Neo4jGraph.open('/tmp/neo4j')
==>neo4jgraph[Community [/tmp/neo4j]]
gremlin> strategy = ElementIdStrategy.build().create()
==>ElementIdStrategy
gremlin> g = graph.traversal().withStrategies(strategy)
==>graphtraversalsource[neo4jgraph[Community [/tmp/neo4j]], standard]
gremlin> g.addV().property(id, '42a').id()
==>42a
Note
用于存储分配的标识符的key应该在底层图形数据库中建立索引。如果没有建立索引,那么查找使用这些标识符的元素将执行线性扫描。
事件策略
EventStrategy的目的是在遍历内发生对底层Graph的更改时,将事件引发到一个或多个MutationListener对象。这种策略对记录更改,触发基于更改的某些操作或在遍历期间需要通知某些变异操作的任何应用程序非常有用。如果事务回滚,则重置事件队列。
以下事件引发MutationListener:
New vertex
New edge
Vertex property changed
Edge property changed
Vertex property removed
Edge property removed
Vertex removed
Edge removed
要开始处理来自Traversal的事件,首先要实现MutationListener接口。此实现的一个示例是ConsoleMutationListener,它将输出写入每个事件的控制台。示例如下:
gremlin> graph = TinkerFactory.createModern()
==>tinkergraph[vertices:6 edges:6]
gremlin> l = new ConsoleMutationListener(graph)
==>MutationListener[tinkergraph[vertices:6 edges:6]]
gremlin> strategy = EventStrategy.build().addListener(l).create()
==>EventStrategy
gremlin> g = graph.traversal().withStrategies(strategy)
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.addV().property('name','stephen')
Vertex [v[13]] added to graph [tinkergraph[vertices:7 edges:6]]
==>v[13]
gremlin> g.E().drop()
Edge [e[7][1-knows->2]] removed from graph [tinkergraph[vertices:7 edges:6]]
Edge [e[8][1-knows->4]] removed from graph [tinkergraph[vertices:7 edges:5]]
Edge [e[9][1-created->3]] removed from graph [tinkergraph[vertices:7 edges:4]]
Edge [e[10][4-created->5]] removed from graph [tinkergraph[vertices:7 edges:3]]
Edge [e[11][4-created->3]] removed from graph [tinkergraph[vertices:7 edges:2]]
Edge [e[12][6-created->3]] removed from graph [tinkergraph[vertices:7 edges:1]]
Note
EventStrategy并不意味着用于跟踪不同进程间的全局变化。换句话说,一个JVM进程中的突变不会作为不同JVM进程中的事件引发。
分区策略
PartitionStrategy将图的顶点和边分割成String命名的分区(如桶,子图等)。

PartitionStrategy中有三种主要配置:
- 分区键(Partition Key) - 以字符串值的属性key来表示的分区。
- 写分区(Write Partition) - 一个字符串,表示将来所有未来写入元素的分区。
- 读分区(Read Partitions) - 一个字符串集合
Set<String>表示可以读取的分区。
使用分区策略的一个例子:
gremlin> graph = TinkerFactory.createModern()
==>tinkergraph[vertices:6 edges:6]
gremlin> strategyA = PartitionStrategy.build().partitionKey("_partition").writePartition("a").readPartitions("a").create()
==>PartitionStrategy
gremlin> strategyB = PartitionStrategy.build().partitionKey("_partition").writePartition("b").readPartitions("b").create()
==>PartitionStrategy
gremlin> gA = graph.traversal().withStrategies(strategyA)
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> gA.addV() // this vertex has a property of {_partition:"a"}
==>v[13]
gremlin> gB = graph.traversal().withStrategies(strategyB)
==>graphtraversalsource[tinkergraph[vertices:7 edges:6], standard]
gremlin> gB.addV() // this vertex has a property of {_partition:"b"}
==>v[15]
gremlin> gA.V()
==>v[13]
gremlin> gB.V()
==>v[15]
通过将元素写入特定分区,然后限制读取分区,开发人员可以在单个地址空间内创建多个图形。此外,通过支持分区之间的引用,可以合并这些多个图(即连接分区)。
Note
如果Graph可以支持元属性,并且在构建PartitionStrategy时将includeMetaProperties值设置为true,则分区也可能扩展到VertexProperty元素。
只读策略
ReadOnlyStrategy 如其名称所示,如果Traversal内有任何改变的步骤,则应用此策略的遍历将抛出IllegalStateException。
子图策略
SubgraphStrategy类似于PartitionStrategy,因为它限制了某些顶点,边和顶点属性的遍历。
下例使用相同的查询对是否使用子图策略的两种情景进行查询,其中子图策略为:创建一个SubgraphStrategy,其中顶点属性不能有一个endTime属性。
gremlin> graph = TinkerFactory.createTheCrew()
==>tinkergraph[vertices:6 edges:14]
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:14], standard]
gremlin> g.V().as('a').values('location').as('b'). //1\
select('a','b').by('name').by()
==>[a:marko,b:san diego]
==>[a:marko,b:santa cruz]
==>[a:marko,b:brussels]
==>[a:marko,b:santa fe]
==>[a:stephen,b:centreville]
==>[a:stephen,b:dulles]
==>[a:stephen,b:purcellville]
==>[a:matthias,b:bremen]
==>[a:matthias,b:baltimore]
==>[a:matthias,b:oakland]
==>[a:matthias,b:seattle]
==>[a:daniel,b:spremberg]
==>[a:daniel,b:kaiserslautern]
==>[a:daniel,b:aachen]
gremlin> g = g.withStrategies(SubgraphStrategy.build().vertexProperties(hasNot('endTime')).create()) //2\
==>graphtraversalsource[tinkergraph[vertices:6 edges:14], standard]
gremlin> g.V().as('a').values('location').as('b'). //3\
select('a','b').by('name').by()
==>[a:marko,b:santa fe]
==>[a:stephen,b:purcellville]
==>[a:matthias,b:seattle]
==>[a:daniel,b:aachen]
来源: http://tinkerpop.apache.org/docs/3.2.6/reference/#_subgraphstrategy
下面的示例使用所有三个过滤器:vertex,edge和vertex property。Vertices必须居住(location属性)在三个以上的地方或者没有居住信息,Edges必须标注为“develops”,VertexProperties必须是当前位置或没有位置(location)属性。
gremlin> graph = TinkerFactory.createTheCrew()
==>tinkergraph[vertices:6 edges:14]
gremlin> g = graph.traversal().withStrategies(SubgraphStrategy.build().
vertices(or(hasNot('location'),properties('location').count().is(gt(3)))).
edges(hasLabel('develops')).
vertexProperties(or(hasLabel(neq('location')),hasNot('endTime'))).create())
==>graphtraversalsource[tinkergraph[vertices:6 edges:14], standard]
gremlin> g.V().valueMap(true)
==>[name:[marko],label:person,location:[santa fe],id:1]
==>[name:[matthias],label:person,location:[seattle],id:8]
==>[name:[gremlin],label:software,id:10]
==>[name:[tinkergraph],label:software,id:11]
gremlin> g.E().valueMap(true)
==>[label:develops,id:13,since:2009]
==>[label:develops,id:14,since:2010]
==>[label:develops,id:21,since:2012]
gremlin> g.V().outE().inV().path().by('name').by(label).by('name')
==>[marko,develops,gremlin]
==>[marko,develops,tinkergraph]
==>[matthias,develops,gremlin]
gremlin>
TinkerPop中的遍历:图的遍历策略的更多相关文章
- TinkerPop中的遍历:图的遍历步骤(3/3)
48 Project Step project() 步骤(map)将当前对象投射到由提供的标签键入的Map<String,Object>中. gremlin> g.V().out(' ...
- TinkerPop中的遍历:图的遍历步骤(1/3)
图遍历步骤(Graph Traversal Steps) 在最一般的层次上,Traversal<S,E>实现了Iterator,S代表起点,E代表结束.遍历由四个主要组成部分组成: Ste ...
- 树的三种DFS策略(前序、中序、后序)遍历
之前刷leetcode的时候,知道求排列组合都需要深度优先搜索(DFS), 那么前序.中序.后序遍历是什么鬼,一直傻傻的分不清楚.直到后来才知道,原来它们只是DFS的三种不同策略. N = Node( ...
- 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)
图的遍历的定义: 从图的某个顶点出发访问遍图中所有顶点,且每个顶点仅被访问一次.(连通图与非连通图) 深度优先遍历(DFS): 1.访问指定的起始顶点: 2.若当前访问的顶点的邻接顶点有未被访问的,则 ...
- Java中关于HashMap的元素遍历的顺序问题
Java中关于HashMap的元素遍历的顺序问题 今天在使用如下的方式遍历HashMap里面的元素时 1 for (Entry<String, String> entry : hashMa ...
- C++编程练习(9)----“图的存储结构以及图的遍历“(邻接矩阵、深度优先遍历、广度优先遍历)
图的存储结构 1)邻接矩阵 用两个数组来表示图,一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中边或弧的信息. 2)邻接表 3)十字链表 4)邻接多重表 5)边集数组 本文只用代码实现用 ...
- Kruskal和prime算法的类实现,图的遍历BFS算法。
一.图的遍历 #include<iostream> #include<queue> #include<vector> using namespace std; in ...
- 图的遍历——DFS(矩形空间)
首先,这里的图不是指的我们一般所说的图结构,而是大小为M*N的矩形区域(也可以看成是一个矩阵).而关于矩形区域的遍历问题经常出现,如“寻找矩阵中的路径”.“找到矩形区域的某个特殊点”等等之类的题目,在 ...
- 图的遍历——DFS和BFS模板(一般的图)
关于图的遍历,通常有深度优先搜索(DFS)和广度优先搜索(BFS),本文结合一般的图结构(邻接矩阵和邻接表),给出两种遍历算法的模板 1.深度优先搜索(DFS) #include<iostrea ...
随机推荐
- 用php实现斐波那契数列
//1 1 2 3 5 8 13 ....//观察数列 你会发现下一个数是如何得来的 // f(3) = f(2) + f(1) f(4)=f(3)+f(2) f(18 ...
- set/multiset容器
一.二叉树基本概念 二叉树就是任何节点最多只允许有两个子节点.分别是左子节点和右子节点. 二叉搜索树,是指二叉树中的节点按照一定的规则进行排序,使得对二叉树中元素访问更加高效.二叉搜索树的放置规则是: ...
- Element header-row-style设置多个属性
方式1: 直接在标签上添加上属性值: <el-table :header-cell-style="{background:'#F3F4F7',color:'#555'}" & ...
- 利用sort对数组快速排序
// sort内部使用快速排序,每次比较两个元素大小的时候如果没有参数,则直接判断字母表,如果有参数,则把正在比较的两个参数传入自定义方法并调用(正在比较的两个数会传给自定义方法的v1.v2),如果返 ...
- 使用 DOM对象,控制HTML元素 来制作的一个简单的表格
制作一个表格,显示班级的学生信息. 要求: 1. 鼠标移到不同行上时背景色改为色值为 red,移开鼠标时则恢复为原背景色 white 2. 点击添加按钮,能动态在最后添加一行 3. 点击删除按钮,则删 ...
- Makefile 自动产生依赖 ***
代码如下: 其实这里主要是为每个C文件建立一个同名的后缀为.d.该文件的作用是使用gcc的-M属性来自动生成.o文件的头文件依赖关系. 第1,2,4都好理解. 第2行解释: 使用gcc -M 的属性将 ...
- Angular5学习笔记 - 创建服务(九)
一.创建服务 ng generate service service-name #简写 ng g s component-name ng g s services/userService 二.效果 三 ...
- Oracle之into
), NVL() INTO SALE_ID, STORE_ID FROM SALEFROMSTORE WHERE ORDERID = IN_ORDER_ID; 这里要注意,into的时候是一个sele ...
- java代码equals方法
package com.bc; public class Test_6 { // 我们知道java中的每个类都继承自Object类,equals是Object方法之一 String name; int ...
- Regexp:正则表达式应用——实例应用
ylbtech-Regexp:正则表达式应用——实例应用 1. 实例应用返回顶部 1. 1.验证用户名和密码:("^[a-zA-Z]\w{5,15}$")正确格式:"[A ...