过滤与转换 #

一、过滤操作概述 #

1.1 什么是过滤 #

过滤是从遍历流中选择满足特定条件的元素的操作。

text
过滤操作分类:
├── 属性过滤:has(), hasNot()
├── 条件过滤:filter(), where()
├── 标签过滤:hasLabel()
├── 去重:dedup()
└── 逻辑过滤:and(), or(), not()

二、属性过滤 #

2.1 has() - 基本过滤 #

gremlin
// 存在属性
g.V().has('name')

// 精确匹配
g.V().has('name', 'Tom')

// 比较操作
g.V().has('age', gt(25))
g.V().has('age', gte(25))
g.V().has('age', lt(40))
g.V().has('age', lte(40))
g.V().has('age', neq(30))

// 区间过滤
g.V().has('age', inside(20, 40))
g.V().has('age', outside(20, 40))

// 列表匹配
g.V().has('name', within('Tom', 'Jerry', 'Mike'))
g.V().has('name', without('Tom', 'Jerry'))

2.2 字符串过滤 #

gremlin
// 包含子串
g.V().has('name', containing('om'))

// 前缀匹配
g.V().has('name', startingWith('T'))

// 后缀匹配
g.V().has('name', endingWith('m'))

// 正则匹配
g.V().has('name', regex('T.*m'))
g.V().has('email', regex('.*@example\\.com'))

2.3 多属性过滤 #

gremlin
// 多条件AND
g.V().has('name', 'Tom').has('age', gt(25))

// 使用has()链式
g.V().has('name', 'Tom').has('age', gt(25)).has('status', 'active')

// 使用and()
g.V().and(
  has('name', 'Tom'),
  has('age', gt(25))
)

2.4 hasNot() - 属性不存在 #

gremlin
// 属性不存在
g.V().hasNot('email')

// 等价于
g.V().not(has('email'))

// 组合使用
g.V().has('name').hasNot('email')

三、标签过滤 #

3.1 hasLabel() #

gremlin
// 单标签
g.V().hasLabel('person')

// 多标签(OR关系)
g.V().hasLabel('person', 'employee', 'manager')

// 边标签
g.E().hasLabel('knows', 'follows')

// 组合过滤
g.V().hasLabel('person').has('status', 'active')

3.2 hasKey()/hasValue() #

gremlin
// 属性键存在
g.V().hasKey('name', 'email')

// 属性值存在
g.V().hasValue('Tom', 'Jerry')

// 组合使用
g.V().properties().hasKey('name')

四、条件过滤 #

4.1 filter() - 自定义过滤 #

gremlin
// 使用filter
g.V().filter(outE().count().is(gt(0)))

// 复杂条件
g.V().filter(
  and(
    outE().count().is(gt(0)),
    inE().count().is(gt(0))
  )
)

// 使用Lambda(注意性能)
g.V().filter { it.get().property('name').orElse('').startsWith('T') }

4.2 where() - 条件过滤 #

gremlin
// 简单条件
g.V().where(outE().count().is(gt(5)))

// 使用标记比较
g.V().as('a').out('knows').as('b').
  where('a', neq('b'))

// 按属性比较
g.V().as('a').out('knows').as('b').
  where('a', neq('b')).by('name')

// 复杂条件
g.V().as('a').out('knows').as('b').
  where('a', lt('b')).by('age')

4.3 where(P) - 谓词过滤 #

gremlin
// 使用谓词
g.V().where(values('age').is(gt(25)))

// 组合谓词
g.V().where(values('age').is(inside(20, 40)))

// 使用within
g.V().where(values('name').is(within('Tom', 'Jerry')))

五、去重操作 #

5.1 dedup() - 基本去重 #

gremlin
// 简单去重
g.V().out('knows').dedup()

// 去重后计数
g.V().out('knows').dedup().count()

// 去重后取值
g.V().out('knows').dedup().values('name')

5.2 dedup().by() - 按属性去重 #

gremlin
// 按属性去重
g.V().dedup().by('name')

// 按计算值去重
g.V().dedup().by(outE().count())

// 按标记去重
g.V().as('a').out('knows').as('b').dedup('a', 'b')

5.3 dedup()与repeat() #

gremlin
// 重复遍历中去重
g.V('1').repeat(out().dedup()).times(3)

// 使用simplePath避免环路
g.V('1').repeat(out().simplePath()).times(3)

六、逻辑操作 #

6.1 and() - 与操作 #

gremlin
// AND条件
g.V().and(
  has('age', gt(25)),
  has('name', startingWith('T'))
)

// 多条件AND
g.V().and(
  has('status', 'active'),
  has('age', inside(20, 40)),
  has('name', startingWith('T'))
)

// 遍历AND
g.V().and(
  outE('knows'),
  outE('follows')
)

6.2 or() - 或操作 #

gremlin
// OR条件
g.V().or(
  has('name', 'Tom'),
  has('name', 'Jerry')
)

// 多条件OR
g.V().or(
  has('status', 'active'),
  has('status', 'pending'),
  has('age', gt(50))
)

// 遍历OR
g.V().or(
  out('knows'),
  out('follows')
)

6.3 not() - 非操作 #

gremlin
// NOT条件
g.V().not(has('status', 'inactive'))

// 复杂NOT
g.V().not(
  or(
    has('status', 'inactive'),
    has('age', lt(18))
  )
)

// NOT遍历
g.V().not(out('knows'))

七、转换操作概述 #

7.1 什么是转换 #

转换是将遍历流中的元素映射为其他形式的操作。

text
转换操作分类:
├── 映射:map(), flatMap()
├── 选择:select(), project()
├── 值提取:values(), valueMap()
├── 合并:union(), coalesce()
└── 计算:math(), sack()

八、映射操作 #

8.1 map() - 一对一映射 #

gremlin
// 映射属性
g.V().map(values('name'))

// 映射计算值
g.V().map(outE().count())

// 映射对象
g.V().map(project('name', 'age').by('name').by('age'))

// 复杂映射
g.V().map(
  coalesce(values('nickname'), values('name'))
)

8.2 flatMap() - 一对多映射 #

gremlin
// 展开遍历结果
g.V().flatMap(out('knows'))

// 展开属性值
g.V().flatMap(values('name', 'email'))

// 展开列表
g.V().flatMap(values('tags'))

// 复杂flatMap
g.V().flatMap(
  out('knows').out('knows')
)

8.3 map vs flatMap #

gremlin
// map - 返回单个结果
g.V().map(values('name'))  // 每个顶点返回一个name

// flatMap - 返回多个结果
g.V().flatMap(values('name', 'email'))  // 每个顶点可能返回多个值

九、选择操作 #

9.1 select() - 选择标记 #

gremlin
// 选择单个标记
g.V().as('a').out('knows').as('b').select('a')

// 选择多个标记
g.V().as('a').out('knows').as('b').select('a', 'b')

// 选择属性
g.V().as('a').out('knows').as('b').
  select('a', 'b').by('name')

// 选择所有标记
g.V().as('a').out('knows').as('b').select(all)

9.2 project() - 投影 #

gremlin
// 简单投影
g.V().project('name', 'age').by('name').by('age')

// 复杂投影
g.V().project('name', 'friendCount', 'status').
  by('name').
  by(out('knows').count()).
  by(coalesce(values('status'), constant('unknown')))

// 嵌套投影
g.V().project('person', 'friends').
  by(valueMap('name', 'age')).
  by(out('knows').values('name').fold())

9.3 values() - 提取值 #

gremlin
// 单个属性
g.V().values('name')

// 多个属性
g.V().values('name', 'age')

// 所有属性
g.V().values()

// 属性对象
g.V().properties('name')

9.4 valueMap() - 属性映射 #

gremlin
// 属性映射
g.V().valueMap()

// 指定属性
g.V().valueMap('name', 'age')

// 包含ID和标签
g.V().valueMap(true)

// 展开单值
g.V().valueMap().by(unfold())

十、合并操作 #

10.1 union() - 合并遍历 #

gremlin
// 合并结果
g.V('1').union(
  out('knows'),
  out('follows')
)

// 合并不同类型
g.V('1').union(
  out('knows').hasLabel('person'),
  out('follows').hasLabel('person')
).dedup()

// 合并计算
g.V('1').union(
  out('knows').count(),
  in('knows').count()
).sum()

10.2 coalesce() - 首选非空 #

gremlin
// 返回第一个非空结果
g.V().coalesce(
  values('nickname'),
  values('name'),
  constant('Unknown')
)

// 遍历合并
g.V('1').coalesce(
  out('knows'),
  out('follows'),
  constant([])
)

// 属性合并
g.V().coalesce(
  has('email').values('email'),
  has('phone').values('phone'),
  constant('No contact')
)

10.3 merge() - 合并结果 #

gremlin
// 合并多个结果
g.V('1').merge(
  out('knows'),
  in('knows')
).dedup()

十一、计算操作 #

11.1 math() - 数学计算 #

gremlin
// 简单计算
g.V().values('price').math('_ * 1.1')  // 加10%

// 使用标记
g.V().as('a').values('price').as('p').
  select('a').values('discount').as('d').
  math('p * (1 - d)')

// 复杂计算
g.V().values('price').math('_ * 0.9 + 10')

11.2 sack() - 背包操作 #

gremlin
// 初始化背包
g.withSack(0).V('1').repeat(
  outE().sack(sum).by('weight').inV()
).times(3).sack()

// 条件背包
g.withSack(0).V().
  sack(sum).by(constant(1)).
  repeat(out()).times(3).
  sack()

// 背包过滤
g.withSack(0).V('1').repeat(
  outE().sack(sum).by('weight').inV()
).emit().sack().is(lt(100))

十二、条件转换 #

12.1 choose() - 条件选择 #

gremlin
// if-else
g.V().choose(
  has('age', gt(30)),
  values('name'),
  constant('Young')
)

// 嵌套choose
g.V().choose(
  has('status', 'active'),
  values('name'),
  choose(
    has('status', 'pending'),
    constant('Pending'),
    constant('Inactive')
  )
)

12.2 option() - 多选项 #

gremlin
// switch-case
g.V().choose(values('status'))
  .option('active', values('name'))
  .option('pending', constant('Pending'))
  .option('inactive', constant('Inactive'))
  .option(none, constant('Unknown'))

12.3 constant() - 常量 #

gremlin
// 返回常量
g.V().constant('Hello')

// 条件常量
g.V().choose(
  has('status', 'active'),
  constant(true),
  constant(false)
)

// 默认值
g.V().coalesce(values('email'), constant('No email'))

十三、实际应用示例 #

13.1 数据清洗 #

gremlin
// 清理空值
g.V().hasLabel('person').
  project('name', 'email', 'phone').
    by('name').
    by(coalesce(values('email'), constant('N/A'))).
    by(coalesce(values('phone'), constant('N/A')))

// 格式化输出
g.V().hasLabel('person').
  map(
    project('fullName', 'contact').
      by(concat(values('firstName'), constant(' '), values('lastName'))).
      by(coalesce(values('email'), values('phone'), constant('No contact')))
  )

13.2 数据转换 #

gremlin
// 类型转换
g.V().hasLabel('product').
  project('name', 'price', 'priceWithTax').
    by('name').
    by('price').
    by(values('price').math('_ * 1.1'))

// 状态转换
g.V().hasLabel('order').
  project('orderId', 'status', 'statusText').
    by('orderId').
    by('status').
    by(choose(values('status'))
      .option('pending', constant('待处理'))
      .option('processing', constant('处理中'))
      .option('completed', constant('已完成'))
      .option(none, constant('未知')))

13.3 数据聚合 #

gremlin
// 分组统计
g.V().hasLabel('person').
  group().
    by('department').
    by(project('count', 'avgAge', 'names').
      by(count()).
      by(values('age').mean()).
      by(values('name').fold())
    )

// 多维度聚合
g.V().hasLabel('order').
  group().
    by('status').
    by(project('count', 'totalAmount').
      by(count()).
      by(values('amount').sum())
    )

十四、总结 #

过滤操作要点:

操作 语法 说明
属性过滤 has() 按属性过滤
条件过滤 filter(), where() 自定义条件
去重 dedup() 去除重复
逻辑操作 and(), or(), not() 逻辑组合

转换操作要点:

操作 语法 说明
映射 map(), flatMap() 元素映射
选择 select(), project() 选择数据
合并 union(), coalesce() 合并结果
计算 math(), sack() 数学计算

下一步,让我们学习SPARQL基础!

最后更新:2026-03-27