如何从图的Edge属性提取Substring并优化Gremlin查询
问题描述
需要从图中company-company类型边的ID字段提取子串生成shr_id,同时优化查询输出格式以匹配预期结果。
图结构初始化代码
g.addV('company').property(id,'SHRTST01').property('name','Alphabet').next() g.addV('company').property(id,'SHRTST02').property('name','Google').next() g.addV('company').property(id,'SHRTST03').property('name','Youtube').next() g.addV('company').property(id,'SHRTST05').property('name','YoutubeKids').next() g.addV('person').property(id,'SHRTST01_1900-01-01_1_1').property('bu_id', 'SHRTST01_1900-01-01_1_1').property('name', 'W Karl David Laxton').next() g.addV('person').property(id,'SHRTST02_1900-01-01_1_1').property('bu_id', 'SHRTST02_1900-01-01_1_1').property('name', 'Steven H Strong').next() g.addE('HAS_SHRHLDING_PC_TO').from(__.V('SHRTST01')).to(__.V('SHRTST01_1900-01-01_1_1')).property(id,'SHRTST01_HAS_SHRHLDING_PC_TO_SHRTST01_1900-01-01_1_1').property('perc_value', 30).next() g.addE('HAS_VOTING_PC_TO').from(__.V('SHRTST01')).to(__.V('SHRTST01_1900-01-01_1_1')).property(id,'SHRTST01_HAS_VOTING_PC_TO_SHRTST01_1900-01-01_1_1').property('perc_value', 50).next() g.addE('HAS_SHRHLDING_PC_TO').from(__.V('SHRTST01')).to(__.V('SHRTST02')).property(id,'SHRTST01_HAS_SHRHLDING_PC_TO_SHRTST02_2002-01-01_2_2').property('perc_value', 75).next() g.addE('HAS_VOTING_PC_TO').from(__.V('SHRTST01')).to(__.V('SHRTST02')).property(id,'SHRTST01_HAS_VOTING_PC_TO_SHRTST02_2002-01-01_2_2').property('perc_value', 50).next() g.addE('HAS_SHRHLDING_PC_TO').from(__.V('SHRTST02')).to(__.V('SHRTST02_1900-01-01_1_1')).property(id,'SHRTST02_HAS_SHRHLDING_PC_TO_SHRTST02_1900-01-01_1_1').property('perc_value', 25).next() g.addE('HAS_VOTING_PC_TO').from(__.V('SHRTST02')).to(__.V('SHRTST02_1900-01-01_1_1')).property(id,'SHRTST02_HAS_VOTING_PC_TO_SHRTST02_1900-01-01_1_1').property('perc_value', 23).next() g.addE('HAS_SHRHLDING_PC_TO').from(__.V('SHRTST02')).to(__.V('SHRTST03')).property(id,'SHRTST02_HAS_SHRHLDING_PC_TO_SHRTST03_2002-01-01_2_2').property('perc_value', 80).next() g.addE('HAS_VOTING_PC_TO').from(__.V('SHRTST02')).to(__.V('SHRTST03')).property(id,'SHRTST03_HAS_VOTING_PC_TO_SHRTST02_2003-01-01_2_2').property('perc_value', 20).next() g.addE('HAS_SHRHLDING_PC_TO').from(__.V('SHRTST03')).to(__.V('SHRTST05')).property(id,'SHRTST03_HAS_SHRHLDING_PC_TO_SHRTST05_2002-01-01_2_2').property('perc_value', 75).next() g.addE('HAS_VOTING_PC_TO').from(__.V('SHRTST03')).to(__.V('SHRTST05')).property(id,'SHRTST03_HAS_VOTING_PC_TO_SHRTST05_2002-01-01_2_2').property('perc_value', 30).next()
当前查询语句
g.V('SHRTST01').as('crn') .repeat( outE('HAS_SHRHLDING_PC_TO').as('edge_field') .inV() .simplePath()) .until(not(outE())) .emit() .hasLabel('company') .select('crn','edge_field') .project('crn', 'edge_field') .by(select(keys).select('crn')) .by(select(keys).select('edge_field'))
实际输出
{'crn': v[SHRTST01], 'edge_field': e[SHRTST01_HAS_SHRHLDING_PC_TO_SHRTST02_2002-01-01_2_2][SHRTST01-HAS_SHRHLDING_PC_TO->SHRTST02]} {'crn': v[SHRTST01], 'edge_field': e[SHRTST02_HAS_SHRHLDING_PC_TO_SHRTST03_2002-01-01_2_2][SHRTST02-HAS_SHRHLDING_PC_TO->SHRTST03]} {'crn': v[SHRTST01], 'edge_field': e[SHRTST03_HAS_SHRHLDING_PC_TO_SHRTST05_2002-01-01_2_2][SHRTST03-HAS_SHRHLDING_PC_TO->SHRTST05]}
预期输出
{'crn': [SHRTST01], 'edge_field': [SHRTST01_HAS_SHRHLDING_PC_TO_SHRTST02_2002-01-01_2_2], 'shr_id':[SHRTST02_2002-01-01_2_2]} {'crn': [SHRTST01], 'edge_field': [SHRTST02_HAS_SHRHLDING_PC_TO_SHRTST03_2002-01-01_2_2], 'shr_id':[SHRTST03_2002-01-01_2_2]} {'crn': [SHRTST01], 'edge_field': [SHRTST03_HAS_SHRHLDING_PC_TO_SHRTST05_2002-01-01_2_2], 'shr_id':[SHRTST05_2002-01-01_2_2]}
核心问题
- 如何从边ID中提取子串生成
shr_id(shr_id是边ID中_SHRTST之后的部分,例如从SHRTST01_HAS_SHRHLDING_PC_TO_SHRTST02_2002-01-01_2_2提取SHRTST02_2002-01-01_2_2) - 如何优化查询语句,将输出格式调整为预期的数组形式
解决方案
优化后的查询语句
g.V('SHRTST01').as('crn') .repeat( outE('HAS_SHRHLDING_PC_TO').as('edge_field') .inV() .simplePath()) .until(not(outE())) .emit() .hasLabel('company') .project('crn', 'edge_field', 'shr_id') .by(select('crn').id().fold()) .by(select('edge_field').id().fold()) .by(select('edge_field').id().map { it.split('_SHRTST')[1] }.map { "SHRTST${it}" }.fold())
关键说明
- 提取shr_id:
- 利用
split('_SHRTST')将边ID分割为两部分,取索引1的部分,再拼接回SHRTST前缀,得到目标shr_id - 示例:
SHRTST01_HAS_SHRHLDING_PC_TO_SHRTST02_2002-01-01_2_2→ split后得到['SHRTST01_HAS_SHRHLDING_PC_TO', '02_2002-01-01_2_2']→ 拼接后为SHRTST02_2002-01-01_2_2
- 利用
- 输出数组格式:
- 使用
fold()将单个值包装为数组,匹配预期输出格式 - 简化原查询中冗余的嵌套
select操作,直接通过project结合id().fold()获取顶点/边的ID并转为数组
- 使用
- 过滤company-company边:
- 原查询中的
hasLabel('company')已确保只保留指向company的边,符合需求场景
- 原查询中的
更优处理思路
- 避免从ID中提取业务数据:建议创建边时直接将
shr_id作为边属性存储,而非从ID解析。这能避免ID格式变更导致的解析失败,同时提升查询性能 - 简化遍历逻辑:若仅需一级company-company关联,可去掉
repeat和until,直接用outE('HAS_SHRHLDING_PC_TO').inV().hasLabel('company'),减少不必要的递归遍历 - 索引优化:为
company标签的顶点ID、HAS_SHRHLDING_PC_TO边标签创建索引,提升查询遍历效率
内容的提问来源于stack exchange,提问作者SDS
相关产品推荐
相关产品推荐

