Gremlin语法入门 #

一、Gremlin概述 #

1.1 什么是Gremlin #

Gremlin是Apache TinkerPop图计算框架的图遍历语言,用于查询和操作属性图数据。

text
Gremlin特点:
├── 函数式编程风格
├── 流式数据处理
├── 支持复杂图遍历
├── 多语言驱动支持
└── 可扩展性强

1.2 基本结构 #

gremlin
// 基本结构
g.遍历源.遍历步骤1().遍历步骤2()...终端步骤()

// 示例
g.V().hasLabel('person').values('name').limit(10)

1.3 遍历步骤分类 #

text
遍历步骤分类:
├── 源步骤(Source Steps)
├── 过滤步骤(Filter Steps)
├── 变换步骤(Transform Steps)
├── 侧效步骤(SideEffect Steps)
└── 终端步骤(Terminal Steps)

二、源步骤 #

2.1 V() - 顶点源 #

gremlin
// 获取所有顶点
g.V()

// 获取指定ID的顶点
g.V('1')
g.V('1', '2', '3')

// 获取指定标签的顶点
g.V().hasLabel('person')

2.2 E() - 边源 #

gremlin
// 获取所有边
g.E()

// 获取指定ID的边
g.E('e1')
g.E('e1', 'e2', 'e3')

// 获取指定标签的边
g.E().hasLabel('knows')

2.3 inject() - 注入数据 #

gremlin
// 注入值
g.inject(1, 2, 3)

// 注入对象
g.inject(['name': 'Tom', 'age': 30])

// 用于批量操作
g.inject(['Tom', 'Jerry', 'Mike']).unfold().addV('person').property('name', identity)

三、过滤步骤 #

3.1 has() - 属性过滤 #

gremlin
// 精确匹配
g.V().has('name', 'Tom')
g.V().has('name', eq('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))   // 20 < age < 40
g.V().has('age', outside(20, 40))  // age < 20 或 age > 40

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

// 字符串匹配
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'))

3.2 hasLabel() - 标签过滤 #

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

// 多标签
g.V().hasLabel('person', 'employee')

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

3.3 hasNot() - 属性不存在 #

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

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

3.4 filter() - 条件过滤 #

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

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

3.5 where() - 条件过滤 #

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

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

// 使用by修饰
g.V().as('a').out('knows').as('b').
  where('a', neq('b')).by('name')

3.6 dedup() - 去重 #

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

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

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

3.7 逻辑操作 #

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

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

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

四、变换步骤 #

4.1 out()/in()/both() - 边遍历 #

gremlin
// 出边遍历
g.V('1').out()           // 所有出边
g.V('1').out('knows')    // 指定标签出边

// 入边遍历
g.V('1').in()            // 所有入边
g.V('1').in('knows')     // 指定标签入边

// 双向遍历
g.V('1').both()          // 所有边
g.V('1').both('knows')   // 指定标签双向边

4.2 outE()/inE()/bothE() - 获取边 #

gremlin
// 获取出边
g.V('1').outE()
g.V('1').outE('knows')

// 获取入边
g.V('1').inE()
g.V('1').inE('knows')

// 获取所有边
g.V('1').bothE()

4.3 inV()/outV()/bothV() - 获取顶点 #

gremlin
// 从边获取顶点
g.E('e1').inV()   // 入顶点
g.E('e1').outV()  // 出顶点
g.E('e1').bothV() // 两个顶点

// 链式操作
g.V('1').outE().inV()  // 等同于 g.V('1').out()
g.V('1').inE().outV()  // 等同于 g.V('1').in()

4.4 map()/flatMap() - 映射 #

gremlin
// map - 一对一映射
g.V().map(values('name'))
g.V().map(outE().count())

// flatMap - 一对多映射
g.V().flatMap(out('knows'))
g.V().flatMap(values('name', 'email'))

4.5 select() - 选择 #

gremlin
// 选择标记
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)

4.6 path() - 路径 #

gremlin
// 获取路径
g.V('1').out('knows').path()

// 路径属性
g.V('1').out('knows').path().by('name')

// 简单路径(无环)
g.V('1').repeat(out()).times(3).simplePath()

4.7 values()/valueMap() - 获取值 #

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

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

// 获取所有属性值
g.V().values()

// 获取属性映射
g.V().valueMap()

// 获取属性映射(包含ID和标签)
g.V().valueMap(true)

五、聚合步骤 #

5.1 count() - 计数 #

gremlin
// 计数
g.V().count()

// 条件计数
g.V().has('status', 'active').count()

// 分组计数
g.V().groupCount().by('status')

5.2 group() - 分组 #

gremlin
// 简单分组
g.V().group().by('status')

// 分组聚合
g.V().group().
  by('status').
  by('age', mean())

// 多级分组
g.V().group().
  by('status').
  by(group().by('department'))

5.3 order() - 排序 #

gremlin
// 升序排序
g.V().order().by('name')

// 降序排序
g.V().order().by('name', desc)

// 多属性排序
g.V().order().by('status', asc).by('name', asc)

// 按计算值排序
g.V().order().by(outE().count(), desc)

5.4 limit()/range() - 分页 #

gremlin
// 限制数量
g.V().limit(10)

// 跳过前N条
g.V().range(10, 20)  // 第11-20条

// Tail
g.V().order().by('name').tail(10)

5.5 sum()/mean()/max()/min() - 聚合 #

gremlin
// 求和
g.V().values('age').sum()

// 平均值
g.V().values('age').mean()

// 最大值
g.V().values('age').max()

// 最小值
g.V().values('age').min()

六、终端步骤 #

6.1 toList()/next()/iterate() #

gremlin
// 返回列表
g.V().toList()

// 返回下一个
g.V().next()
g.V().next(5)  // 返回5个

// 执行遍历(不返回结果)
g.addV('person').property('name', 'Tom').iterate()

6.2 hasNext()/tryNext() #

gremlin
// 检查是否有结果
g.V().has('name', 'Tom').hasNext()

// 尝试获取下一个(返回Optional)
g.V().has('name', 'Tom').tryNext()

七、修改步骤 #

7.1 addV() - 添加顶点 #

gremlin
// 添加顶点
g.addV('person').property('name', 'Tom')

// 批量添加
g.addV('person').property('name', 'Tom').
  addV('person').property('name', 'Jerry')

7.2 addE() - 添加边 #

gremlin
// 添加边
g.addE('knows').from(V('1')).to(V('2'))

// 从遍历添加
g.V('1').addE('knows').to(V('2'))

7.3 property() - 设置属性 #

gremlin
// 设置属性
g.V('1').property('age', 30)

// 设置多值属性
g.V('1').property(list, 'phone', '123-456-7890')

7.4 drop() - 删除 #

gremlin
// 删除顶点
g.V('1').drop()

// 删除边
g.E('e1').drop()

// 删除属性
g.V('1').properties('age').drop()

八、重复遍历 #

8.1 repeat() - 重复遍历 #

gremlin
// 重复N次
g.V('1').repeat(out()).times(3)

// 直到条件
g.V('1').repeat(out()).until(has('name', 'Jerry'))

// 发射中间结果
g.V('1').repeat(out()).emit().times(3)

// 条件发射
g.V('1').repeat(out()).emit(has('status', 'active')).times(3)

8.2 until()/emit() - 条件控制 #

gremlin
// until - 终止条件
g.V('1').repeat(out()).until(outE().count().is(0))

// emit - 发射条件
g.V('1').repeat(out()).emit().until(has('name', 'Jerry'))

// emit在repeat前
g.V('1').emit().repeat(out()).times(3)

九、合并操作 #

9.1 union() - 合并 #

gremlin
// 合并多个遍历
g.V('1').union(
  out('knows'),
  out('follows')
)

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

9.2 coalesce() - 首选非空 #

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

9.3 choose() - 条件选择 #

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

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

十、实用技巧 #

10.1 性能优化 #

gremlin
// 使用标签过滤
g.V().hasLabel('person').has('name', 'Tom')

// 使用limit限制结果
g.V().limit(100)

// 使用索引属性
g.V().has('userId', 'user_001')

// 避免全图扫描
g.V().hasLabel('person')  // 好
g.V()  // 避免

10.2 调试技巧 #

gremlin
// 查看中间结果
g.V().hasLabel('person').as('persons').
  out('knows').as('friends').
  select('persons', 'friends')

// 计算中间数量
g.V().hasLabel('person').count().as('personCount').
  select('personCount')

// 使用profile分析
g.V().hasLabel('person').out('knows').profile()

十一、总结 #

Gremlin语法要点:

类别 步骤 说明
源步骤 V(), E() 遍历起点
过滤步骤 has(), filter(), where() 过滤数据
变换步骤 out(), in(), map() 变换数据
聚合步骤 count(), group(), order() 聚合数据
终端步骤 toList(), next(), iterate() 执行遍历

下一步,让我们学习遍历操作!

最后更新:2026-03-27