• 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命名的分区(如桶,子图等)。
    partition graph

    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> 
    
  • 相关阅读:
    java爬虫系列目录
    java爬虫系列第五讲-如何使用代理防止爬虫被屏蔽?
    java爬虫系列第三讲-获取页面中绝对路径的各种方法
    java爬虫系列第二讲-爬取最新动作电影《海王》迅雷下载地址
    java爬虫系列第一讲-爬虫入门
    spring aop中pointcut表达式完整版
    wkhtmltox实现网页转换成图片或pdf
    spring通知执行的顺序
    nginx代理(正向代理和反向代理)
    nginx热加载、热升级、回滚
  • 原文地址:https://www.cnblogs.com/myitroad/p/7778514.html
Copyright © 2020-2023  润新知