遍历策略

一个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中的遍历:图的遍历策略的更多相关文章

  1. TinkerPop中的遍历:图的遍历步骤(3/3)

    48 Project Step project() 步骤(map)将当前对象投射到由提供的标签键入的Map<String,Object>中. gremlin> g.V().out(' ...

  2. TinkerPop中的遍历:图的遍历步骤(1/3)

    图遍历步骤(Graph Traversal Steps) 在最一般的层次上,Traversal<S,E>实现了Iterator,S代表起点,E代表结束.遍历由四个主要组成部分组成: Ste ...

  3. 树的三种DFS策略(前序、中序、后序)遍历

    之前刷leetcode的时候,知道求排列组合都需要深度优先搜索(DFS), 那么前序.中序.后序遍历是什么鬼,一直傻傻的分不清楚.直到后来才知道,原来它们只是DFS的三种不同策略. N = Node( ...

  4. 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)

    图的遍历的定义: 从图的某个顶点出发访问遍图中所有顶点,且每个顶点仅被访问一次.(连通图与非连通图) 深度优先遍历(DFS): 1.访问指定的起始顶点: 2.若当前访问的顶点的邻接顶点有未被访问的,则 ...

  5. Java中关于HashMap的元素遍历的顺序问题

    Java中关于HashMap的元素遍历的顺序问题 今天在使用如下的方式遍历HashMap里面的元素时 1 for (Entry<String, String> entry : hashMa ...

  6. C++编程练习(9)----“图的存储结构以及图的遍历“(邻接矩阵、深度优先遍历、广度优先遍历)

    图的存储结构 1)邻接矩阵 用两个数组来表示图,一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中边或弧的信息. 2)邻接表 3)十字链表 4)邻接多重表 5)边集数组 本文只用代码实现用 ...

  7. Kruskal和prime算法的类实现,图的遍历BFS算法。

    一.图的遍历 #include<iostream> #include<queue> #include<vector> using namespace std; in ...

  8. 图的遍历——DFS(矩形空间)

    首先,这里的图不是指的我们一般所说的图结构,而是大小为M*N的矩形区域(也可以看成是一个矩阵).而关于矩形区域的遍历问题经常出现,如“寻找矩阵中的路径”.“找到矩形区域的某个特殊点”等等之类的题目,在 ...

  9. 图的遍历——DFS和BFS模板(一般的图)

    关于图的遍历,通常有深度优先搜索(DFS)和广度优先搜索(BFS),本文结合一般的图结构(邻接矩阵和邻接表),给出两种遍历算法的模板 1.深度优先搜索(DFS) #include<iostrea ...

随机推荐

  1. rpy2的安装问题?【解决】

    https://www.zhihu.com/question/46555829 http://blog.sciencenet.cn/blog-365459-901335.html

  2. Codeforces 802 ABC. Heidi and Library

    题目大意 你需要保证第\(i\)天时有第\(a_i\)种书.你可以在任何一天买书,买第\(i\)种书的代价为\(c_i\). 你最多同时拥有\(k\)本书,如果此时再买书,则必须先扔掉已拥有的一本书. ...

  3. java 简单实现socket

    server端 package socket; import java.io.BufferedReader; import java.io.IOException; import java.io.In ...

  4. Oracle 12C 新特性之 db默认字符集AL32UTF8、PDB支持不同字符集

    一. db默认字符集AL32UTF8Specify the database character set when you create the database. Starting from Ora ...

  5. loj 2542 随机游走 —— 最值反演+树上期望DP+fmt

    题目:https://loj.ac/problem/2542 因为走到所有点的期望就是所有点期望的最大值,所以先最值反演一下,问题变成从根走到一个点集任意一点就停止的期望值: 设 \( f[x] \) ...

  6. 把python2.6升级到python2.7(同样适用于把python2升级到python3)

    在启用https过程中,在生成CSR(证书请求文件)时,报错了,说python2.6已被python团队抛弃了,所以升级python到2.7 话不多说,直接上代码: 步骤1:下载python2.7.1 ...

  7. LTE-V2X车联网无线通信技术发展

    2017年9月7日,国家制造强国建设领导小组车联网产业发展专项委员会第一次全体会议在北京召开.会议要求“要加大关键产品研发攻关力度,完善测试验证.技术评价.质量认证等公共服务平台,促进LTE-V2X车 ...

  8. 学习Linux相关书籍

    要推荐的书,我在<那两年炼就的Android内功修养>这篇文章中有提到,这里再列一下出来: 语言类: <深度探索C++对象模型>,对应的英文版是<Inside C+++  ...

  9. spring boot 学习10 定义springboot的两种方法

    使用spring boot的两种方法: A:继承spring-boot-starter-parent项目 这种方式很简单,只需要在POM里面添加parent父工程即可. B: 如果你不喜欢继承spri ...

  10. eval(function(p,a,c,k,e,r)解密程序

    以eval(function(p,a,c,k,e,r){e=function(c)开头的js文件是经过加密的 使用下面方法可以对js文件进行加密.解密 步骤:1.新建html页面,内容如下列代码 2. ...