「JanusGraph-Gremlin」高级语法sack()局部数据结构

sack(麻袋)帮助人们更细致有效地解决问题

在某些情况下,人们正在编写使用路径信息进行数据聚合的Gremlin遍历。通常,人们将使用path()然后再执行一些过滤以“减少”路径中的数据获得特定结果。

不幸的是,这是低效的,因为路径计算是昂贵的,且是不可以合并的,计算全部路径再过滤相当耗资源和时间且笨拙。

 

原理

sack是相对于每个遍历者的局部数据结构,与aggregate()/store()/group(x)/subgraph(x)...全局数据结构不同。这意味着每个经过路径的元素都配备了他自己的麻袋。

sack可以包含任何类型的数据结构:

  • 原语:Int,Double,Long,Data...
  • 集合:List,Set,Map

 

Sack的定义

此数据结构的定义应该放在遍历对象之后:

gremlin>g.withSack(1.0). // Define a sack containing an initial double value        
  V().
  ...
 
gremlin>g.withSack([] as Set). // Define a sack containing an initial empty Set        
  V().
  ...
 
gremlin>g.withSack([1,2,3] as Set). // Define a sack containing a pre-initialized Set        
  V().
  ...
 
gremlin>g.withSack([] as List). // Define a sack containing an initial empty List        
  V().
  ...
 
gremlin>g.withSack([:]). // Define a sack containing an initial empty Map        
  V().
  ...
 
gremlin>g.withSack([:].              // Define a sack containing an initial empty Map  
    withDefault{key -> [] as List}). // with default values being an empty list        
  V().
  ...

withSack()Step的完整参数是 withSack(default_data_structure, split_operator, merge_operator)

  • split_operator:当遍历器面向分支并需要复制自身时,split运算符用于分割数据结构。示例:V().has("user","userId", "u861").out("rated")。现在,从用户顶点出现的遍历与对不同电影的评级一样多。因此,用户顶点的sack结构得到重复
  • merge_operator:用于在所有遍历器收敛到单个点时将不同的数据块结构合并在一起。示例:g.V().hasLabel("movie").out("director").has("name", "Woody Allen")。来自许多Movie顶点的遍历正在收敛到单个Person顶点,即Woody Allen。顶点Woody Allen的麻袋是他电影中所有数据结构的合并。如果您没有定义任何合并运算符,则无法合并

注意:对于原始数据类型,split operator == value copy。对于其他数据类型(如集合),如果未定义任何拆分运算符,则相同的对象引用将复制到所有分支遍历器。因此,所有这些遍历者将共享相同的数据结构。要非常小心

 

。。。

 

 

Sack().by()求正弦

gremlin> g.withSack(1).V(1).repeat(sack(sum).by(constant(1))).times(10).emit().sack().math('sin _')
==>0.9092974268256817
==>0.1411200080598672
==>-0.7568024953079282
==>-0.9589242746631385
==>-0.27941549819892586
==>0.6569865987187891
==>0.9893582466233818
==>0.4121184852417566
==>-0.5440211108893698
==>-0.9999902065507035

 

使用sack()进行复杂查询


/**(43)
 * 使用sack()进行复杂查询示例
 * */
//(1)
// 普通查询
//Select all direct flights from SEA to SFO on 8/18/2017, departing time between 6:00 and 10:00 am
g.V().has('StationCode','SEA').
        outE('routes').
            has('LegEffectiveDate',lte(createDate(2017,8,18,0,0,0))).
            has('LegDiscountinueDate',gte(createDate(2017,8,18,0,0,0))).
            has('AircraftSTD',between(createTime(6,0,0),createTime(10,0,0))).
        inV().
            has('StationCode','SFO').path()

//(2)
// 使用sack
//Select all one-stop flights, with one hour connection time, from SFO to SDF on 8/18/2017, departing time between 6:00 and 10:00 am
g.withSack{[M:4472,C:getMaxConnectTime('US','US')]}{it.clone()}.
        V().
            has('StationCode','SFO').
        outE('routes').
            has('LegEffectiveDate',lte(createDate(2017,8,18,0,0,0))).
            has('LegDiscountinueDate',gte(createDate(2017,8,18,0,0,0))).
            has('FlyFri',true).
            has('AircraftSTD',between(createTime(6,0,0),createTime(10,0,0))).
            has('ToAirport',without('SDF')).
            sack{m,e->m['M']=m['M']-e.value('FlightDistance');m['A1']=e.value('AircraftSTA');m}.
            filter{it.sack()['M']>0}.
            order().by('AircraftSTD',incr).
        inV().
        outE('routes').
            has('LegEffectiveDate',lte(createDate(2017,8,18,0,0,0))).
            has('LegDiscountinueDate',gte(createDate(2017,8,18,0,0,0))).
            has('FlyFri',true).
            has('ToAirport','SDF').
            sack{m,e->m['M']=m['M']-e.value('FlightDistance');m['C']=m['C']-getConnectTime(m['A1'],e.value('AircraftSTD'));m}.
            filter{it.sack()['M']>0 && it.sack()['C']>0 && it.get().value('AircraftSTD').after(addTime(it.sack()['A1'],0,60,0))}.
        inV().
        path().
            filter{passCabotage([it.get()[0].value('CountryCode'),it.get()[2].value('CountryCode'),it.get()[4].value('CountryCode')])
                and passNextDay(it.get()[1].value('AircraftSTD'),it.get()[1].value('AircraftSTA'))}

 

未完待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值