基于顶点层级过滤带hideFromParentLevels属性的边(Gremlin/Azure Cosmos)
解决Azure Cosmos Gremlin中基于层级的边过滤问题
我是图数据库与Gremlin的新手,表述若有不清请见谅。我正在使用Azure Cosmos,该数据库存在一些限制,例如无法使用sack。
需求说明
- 当起始顶点在遍历路径中的顶点/边层级之上时,排除树中
hideFromParentLevels设为true的下层边关联的结果; - 如果起始顶点与边关联的顶点处于同一层级,则保留该结果。
示例场景
- 以"Head Office"为起始顶点时,不希望看到"Area 3 NOT ABOVE"(其关联边的
hideFromParentLevels为true); - 若起始顶点替换为"Saffron Walden",则希望显示该内容。
完整数据集
g.addV('hierarchy').as('1'). property(single, 'name', 'Head Office'). property(single, 'type', 0).addV('hierarchy'). as('2'). property(single, 'name', 'Region 1'). property(single, 'type', 1).addV('hierarchy'). as('3'). property(single, 'name', 'Area 1'). property(single, 'type', 2).addV('hierarchy'). as('4'). property(single, 'name', 'Area 2'). property(single, 'type', 2).addV('hierarchy'). as('5'). property(single, 'name', 'Area 3'). property(single, 'type', 2). addV('communication').as('6'). property(single, 'title', 'Communication A'). addV('hierarchy').as('7'). property(single, 'name', 'Saffron Walden'). property(single, 'type', 3).addV('hierarchy'). as('8'). property(single, 'name', 'Brighton'). property(single, 'type', 3).addV('hierarchy'). as('9'). property(single, 'name', 'St Albans'). property(single, 'type', 3).addV('hierarchy'). as('10'). property(single, 'name', 'Southend on Sea'). property(single, 'type', 3).addV('hierarchy'). as('11'). property(single, 'name', 'Cheltenham'). property(single, 'type', 3).addV('hierarchy'). as('12'). property(single, 'name', 'South Harrow'). property(single, 'type', 3).addV('hierarchy'). as('13'). property(single, 'name', 'Epsom'). property(single, 'type', 3).addV('hierarchy'). as('14'). property(single, 'name', 'Dorking'). property(single, 'type', 3).addV('hierarchy'). as('15'). property(single, 'name', 'Stevenage'). property(single, 'type', 3). addV('communication').as('16'). property(single, 'title', 'Area 3 NOT ABOVE'). addE('child').from('1').to('2').addE('child'). from('2').to('4').addE('child').from('2'). to('5').addE('child').from('2').to('3'). addE('child').from('3').to('10'). addE('child').from('3').to('11'). addE('child').from('3').to('12'). addE('child').from('4').to('13'). addE('child').from('4').to('14'). addE('child').from('4').to('15'). addE('child').from('5').to('9').addE('child'). from('5').to('7').addE('child').from('5'). to('8').addE('audience').from('6').to('7'). property('hideFromParentLevels', false). addE('audience').from('6').to('8'). property('hideFromParentLevels', false). addE('audience').from('6').to('9'). property('hideFromParentLevels', false). addE('audience').from('16').to('7'). property('hideFromParentLevels', true). addE('audience').from('16').to('8'). property('hideFromParentLevels', true). addE('audience').from('16').to('9'). property('hideFromParentLevels', true)
当前查询
g.V() .has('name', 'Head Office') .emit() .repeat(__.out()) .in() .hasLabel('communication') .dedup() .values('title')
我能单独过滤hideFromParentLevels属性,但无法结合顶点层级检查实现上述需求。
解决方案
由于Azure Cosmos不支持sack,可以利用顶点的type属性(数值越小层级越高)判断起始顶点与关联顶点的层级关系,结合边的hideFromParentLevels属性过滤结果。
核心逻辑
- 记录起始顶点的
type值; - 遍历到关联的层级顶点时,比较两者
type:- 若起始顶点
type< 关联顶点type(起始层级更高),仅保留hideFromParentLevels=false的边; - 若两者
type相等(同一层级),则保留所有关联结果。
- 若起始顶点
实现查询
以"Head Office"为起始顶点
g.V().has('name', 'Head Office').as('start') .emit() .repeat(out('child')) .in('audience').hasLabel('communication') .where( __.out('audience').as('target') .select('start').values('type').as('startType') .select('target').values('type').as('targetType') .choose( lt('startType', 'targetType'), __.outE('audience').has('hideFromParentLevels', false), __.constant(true) ) ) .dedup() .values('title')
以"Saffron Walden"为起始顶点
仅修改起始顶点条件即可:
g.V().has('name', 'Saffron Walden').as('start') .emit() .repeat(out('child')) .in('audience').hasLabel('communication') .where( __.out('audience').as('target') .select('start').values('type').as('startType') .select('target').values('type').as('targetType') .choose( lt('startType', 'targetType'), __.outE('audience').has('hideFromParentLevels', false), __.constant(true) ) ) .dedup() .values('title')
说明
- 通过
as()标记起始顶点与目标层级顶点,用select()获取两者type值做比较; choose()分支处理两种层级场景,适配Azure Cosmos的功能限制;- 最终通过
dedup()避免重复结果。
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

