sack(麻袋)
帮助人们更细致有效地解决问题
在某些情况下,人们正在编写使用路径信息进行数据聚合的Gremlin遍历。通常,人们将使用path()
然后再执行一些过滤以“减少”路径中的数据获得特定结果。
不幸的是,这是低效的,因为路径计算是昂贵的,且是不可以合并的,计算全部路径再过滤相当耗资源和时间且笨拙。
sack是相对于每个遍历者的局部数据结构,与aggregate()/store()/group(x)/subgraph(x)...
全局数据结构不同。这意味着每个经过路径的元素都配备了他自己的麻袋。
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
/**(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'))}
未完待续。。。