第18期 Gremlin Steps:
sample()
、coin()
、constant()
、inject()
本系列文章的Gremlin示例均在HugeGraph图数据库上执行,环境搭建可参考准备Gremlin执行环境,本文示例均以其中的“TinkerPop关系图”为初始数据。
随机过滤说明
Gremlin支持对遍历器(traversal)上的结果进行采样或者做随机过滤。
sample
: 接受一个整数值,从前一步的遍历器中采样(随机)出最多指定数目的结果;coin
: 字面意思是抛硬币过滤,接受一个浮点值,该浮点值表示硬币出现正面的概率。coin
Step 对前一步的遍历器中的每个元素都抛一次硬币,出现正面则可以通过,反面则被拦截。
sample
Step后能接上by
Step,能以指定的属性为判断依据进行随机过滤。
注入说明
Gremlin允许在遍历器中注入一些默认值或自定义值,比如在分支 Step 中给 else
路径的元素一个默认值,又或者在遍历器过程中人为地加上一些额外的元素。
constant
: 通常用在choose
或coalesce
Step中做辅助输出,为那些不满足条件的元素提供一个默认值;inject
: 能够在流(遍历器)的任何位置注入与当前遍历器同输出类型的对象,当然,也可以作为流的起始 Step 产生数据;
inject
只是在查询过程中添加一些额外的元素,并没有把数据真正地插入到图中
实例讲解
下面通过实例来深入理解每一个操作。
Step
sample()
示例1:
1
2// 从所有顶点的出边中随机选择2条
g.V().outE().sample(2)由于
sample
是随机采样,所以运行结果每次都可能不一样。另外,sample(n)
表示最多采样n
个,如果上一步不够n
个元素自然结果是会小于n
的。示例2:
1
2// 从所以顶点的“name”属性中随机选取3个
g.V().values('name').sample(3)示例3:
1
2// 从所有的“person”中根据“age”随机选择3个
g.V().hasLabel('person').sample(3).by('age')示例4:与
local
联合使用做随机漫游(从某个顶点出发,随机选一条边,走到边上的邻接点;再以该点为起点,继续随机选择边,走到邻接点…)1
2
3
4
5// 从顶点“HugeGraph”出发做3次随机漫游
g.V('3:HugeGraph')
.repeat(local(bothE().sample(1).otherV()))
.times(3)
.path()
第1次:从“HugeGraph”沿着“Szhoney>2>>S3:HugeGraph”走到“zhoney”
第2次:从“zhoney”沿着“Sjaveme>1>>Szhoney”走到“javeme”
第3次:从“javeme”沿着“Sjaveme>1>>Slinary”走到“linary”
Step
coin()
示例1:
1
2// 每个顶点按0.5的概率过滤
g.V().coin(0.5)这一次输出了5个顶点,而总共是有12个顶点的,为什么不是输出6个呢?学过概率论的应该都知道,不解释。我又多执行了两次,输出顶点数分别是5和7。
示例2:
1
2// 每个顶点按0.0的概率过滤
g.V().coin(0.0)示例3:
1
2// 每个顶点按1.0的概率过滤
g.V().coin(1.0).count()避免输出太长,加上
count
。Step
constant()
示例1:
1
2
3
4// 输出所有“person”类顶点的“name”属性,否则输出“inhuman”(非人类)
g.V().choose(hasLabel('person'),
values('name'),
constant('inhuman'))示例2:
1
2
3// 与示例1功能相同,使用“coalesce”Step 实现
g.V().coalesce(hasLabel('person').values('name'),
constant('inhuman'))Step
inject()
示例1:
1
2// 给顶点“HugeGraph”的作者添加一个叫“Tom”的人
g.V('3:HugeGraph').in('created').values('name').inject('Tom')示例2:
1
2
3// 在示例1的基础上计算每个元素的长度(“name”属性值的长度)
g.V('3:HugeGraph').in('created').values('name').inject('Tom')
.map {it.get().length()}可以看到,注入的元素“Tom”与原生的元素一样参与了计算
示例3:
1
2
3// 在示例2的基础上计算走过的路径
g.V('3:HugeGraph').in('created').values('name').inject('Tom')
.map {it.get().length()}.path()这里又能看出注入元素“Tom”与原生的元素的区别,由于“Tom”是在获取“name”属性这一步时才注入的,所以之前的从顶点“HugeGraph”出发,获取其“created”的入顶点这两步“Tom”是没有的。
示例4:
1
2// 使用inject创建出两个元素(顶点的id),并使用该元素作为id获取顶点及其属性“name”
inject('javeme', 'linary', 'zhoney').map {g.V(it.get()).next()}.values('name')1
2// 使用inject创建出一个“person”(顶点label),并使用该元素作为label获取顶点及其属性“name”
inject('person').flatMap {g.V().hasLabel(it.get())}.values('name')