节点与顶点 #

一、顶点概述 #

1.1 什么是顶点 #

顶点是图数据库中最基本的数据实体,用于表示现实世界中的对象。在Neptune中,顶点可以表示人、地点、事物、概念等。

text
顶点组成:
├── 唯一标识符(ID)
├── 标签(Label)
└── 属性集合(Properties)

1.2 顶点特点 #

text
顶点特点:
├── 系统自动分配唯一ID
├── 可有多个标签
├── 可有多个属性
├── 可有多个入边和出边
└── 属性值支持多种数据类型

1.3 顶点结构图 #

text
┌─────────────────────────┐
│       Person            │  ← 标签
│                         │
│  id: "1"                │  ← 系统ID
│  name: "Tom"            │  ← 属性
│  age: 30                │
│  email: "tom@test.com"  │
└─────────────────────────┘
         │
         │ knows
         ▼

二、创建顶点 #

2.1 Gremlin创建顶点 #

创建基本顶点:

gremlin
// 创建空顶点
g.addV()

// 创建带标签的顶点
g.addV('person')

// 创建带属性的顶点
g.addV('person').property('name', 'Tom')

// 创建完整顶点
g.addV('person').
  property('name', 'Tom').
  property('age', 30).
  property('email', 'tom@test.com')

批量创建顶点:

gremlin
// 使用多个addV
g.addV('person').property('name', 'Tom').
  addV('person').property('name', 'Jerry').
  addV('person').property('name', 'Mike')

// 使用unfold批量创建
g.inject(['Tom', 'Jerry', 'Mike']).
  unfold().
  addV('person').
  property('name', identity)

使用参数创建:

python
from gremlin_python.process.traversal import T
from gremlin_python.process.traversal import P

# Python示例
g.addV('person').property('name', 'Tom').property('age', 30).next()

# 批量创建
names = ['Tom', 'Jerry', 'Mike']
for name in names:
    g.addV('person').property('name', name).iterate()

2.2 SPARQL创建顶点 #

创建RDF资源:

sparql
PREFIX ex: <http://example.org/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

INSERT DATA {
  ex:Tom a foaf:Person ;
         foaf:name "Tom" ;
         ex:age 30 ;
         foaf:mbox <mailto:tom@test.com> .
}

批量创建:

sparql
PREFIX ex: <http://example.org/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

INSERT DATA {
  ex:Tom a foaf:Person ; foaf:name "Tom" .
  ex:Jerry a foaf:Person ; foaf:name "Jerry" .
  ex:Mike a foaf:Person ; foaf:name "Mike" .
}

三、查询顶点 #

3.1 基本查询 #

gremlin
// 查询所有顶点
g.V()

// 查询指定ID的顶点
g.V('1')

// 查询指定ID列表的顶点
g.V('1', '2', '3')

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

3.2 按标签查询 #

gremlin
// 查询指定标签的顶点
g.V().hasLabel('person')

// 查询多个标签的顶点
g.V().hasLabel('person', 'employee')

// 查询标签
g.V().label()

3.3 按属性查询 #

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

// 多属性匹配
g.V().has('name', 'Tom').has('age', 30)

// 数值比较
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', inside(20, 40))

// 字符串匹配
g.V().has('name', containing('Tom'))
g.V().has('name', startingWith('T'))
g.V().has('name', endingWith('m'))

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

3.4 复杂查询 #

gremlin
// 组合条件
g.V().hasLabel('person').
  has('age', gt(25)).
  has('name', startingWith('T'))

// 使用where条件
g.V().where(outE('knows').count().is(gt(0)))

// 使用filter
g.V().filter(
  __.properties().count().is(gt(3))
)

// 使用and/or/not
g.V().and(
  has('age', gt(25)),
  has('name', startingWith('T'))
)

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

四、顶点标签 #

4.1 标签概念 #

标签用于对顶点进行分类,一个顶点可以有多个标签。

text
标签作用:
├── 分类顶点类型
├── 加速查询过滤
├── 支持多标签
└── 命名规范:小写、下划线分隔

4.2 添加标签 #

gremlin
// 创建时添加标签
g.addV('person')

// 添加多个标签
g.addV('person').addV('employee')

// 为现有顶点添加标签
g.V('1').addV('manager')

// 注意:Neptune不支持直接添加标签到现有顶点
// 需要使用property设置

4.3 查询标签 #

gremlin
// 获取顶点标签
g.V('1').label()

// 获取所有标签
g.V().label().dedup()

// 按标签统计
g.V().groupCount().by(label)

五、顶点属性 #

5.1 属性操作 #

gremlin
// 添加单个属性
g.V('1').property('name', 'Tom')

// 添加多个属性
g.V('1').
  property('name', 'Tom').
  property('age', 30)

// 添加多值属性
g.V('1').
  property(list, 'email', 'tom@test.com').
  property(list, 'email', 'tom@work.com')

// 获取属性值
g.V('1').values('name')

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

// 获取属性键
g.V('1').keys()

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

// 获取属性对象
g.V('1').properties()

5.2 属性基数 #

text
属性基数类型:
├── single:单值属性(默认)
├── set:集合属性(去重)
└── list:列表属性(允许多值)
gremlin
// 单值属性
g.V('1').property(single, 'name', 'Tom')

// 集合属性
g.V('1').property(set, 'tag', 'important')
g.V('1').property(set, 'tag', 'urgent')

// 列表属性
g.V('1').property(list, 'phone', '123-456-7890')
g.V('1').property(list, 'phone', '098-765-4321')

5.3 更新属性 #

gremlin
// 更新属性值
g.V('1').property('age', 31)

// 条件更新
g.V('1').property('age', 31).has('age', 30)

// 使用合并更新
g.V('1').property('age', 31)

5.4 删除属性 #

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

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

// 删除多值属性中的一个
g.V('1').properties('email').hasValue('old@test.com').drop()

六、顶点ID #

6.1 系统ID #

gremlin
// 获取顶点ID
g.V('1').id()

// 通过ID查询
g.V('1')

// 批量ID查询
g.V('1', '2', '3')

// ID类型
// Neptune使用字符串类型ID

6.2 自定义ID #

gremlin
// Neptune支持自定义ID
g.addV('person').property(T.id, 'user_001').property('name', 'Tom')

// 使用自定义ID查询
g.V('user_001')

七、删除顶点 #

7.1 基本删除 #

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

// 删除多个顶点
g.V('1', '2', '3').drop()

// 条件删除
g.V().has('status', 'inactive').drop()

7.2 级联删除 #

gremlin
// 删除顶点及其所有边
// Neptune会自动删除关联的边
g.V('1').drop()

// 手动删除边后删除顶点
g.V('1').bothE().drop()
g.V('1').drop()

八、顶点遍历 #

8.1 出边遍历 #

gremlin
// 获取所有出边连接的顶点
g.V('1').out()

// 获取指定标签的出边顶点
g.V('1').out('knows')

// 获取多条边标签的出边顶点
g.V('1').out('knows', 'follows')

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

// 获取指定标签的出边
g.V('1').outE('knows')

8.2 入边遍历 #

gremlin
// 获取所有入边连接的顶点
g.V('1').in()

// 获取指定标签的入边顶点
g.V('1').in('knows')

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

// 获取指定标签的入边
g.V('1').inE('knows')

8.3 双向遍历 #

gremlin
// 获取所有边连接的顶点
g.V('1').both()

// 获取指定标签的双向顶点
g.V('1').both('knows')

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

九、顶点统计 #

9.1 计数操作 #

gremlin
// 统计所有顶点数量
g.V().count()

// 统计指定标签顶点数量
g.V().hasLabel('person').count()

// 按标签分组计数
g.V().groupCount().by(label)

// 统计属性值数量
g.V().has('status', 'active').count()

9.2 度统计 #

gremlin
// 出度
g.V('1').outE().count()

// 入度
g.V('1').inE().count()

// 总度
g.V('1').bothE().count()

// 高度节点
g.V().order().by(bothE().count(), desc).limit(10)

// 孤立节点
g.V().where(bothE().count().is(0))

十、最佳实践 #

10.1 标签设计 #

text
标签设计原则:
├── 使用名词命名:person, product, order
├── 使用小写和下划线
├── 保持语义清晰
├── 避免过多标签
└── 考虑查询模式

10.2 属性设计 #

text
属性设计原则:
├── 使用唯一标识属性
├── 属性名使用小驼峰或下划线
├── 避免过大的属性值
├── 合理使用多值属性
└── 保持命名一致性

10.3 性能优化 #

gremlin
// 使用标签过滤
g.V().hasLabel('person')  // 好
g.V().filter(label().is('person'))  // 避免

// 使用属性索引
g.V().has('name', 'Tom')  // 好

// 限制遍历深度
g.V().repeat(out()).times(3)  // 好
g.V().repeat(out()).until(has('name', 'Tom'))  // 注意循环

// 使用limit
g.V().limit(100)  // 好

十一、实际应用示例 #

11.1 用户顶点 #

gremlin
// 创建用户
g.addV('user').
  property('userId', 'user_001').
  property('username', 'tom_hanks').
  property('email', 'tom@example.com').
  property('createdAt', datetime()).
  property('status', 'active')

// 查询活跃用户
g.V().hasLabel('user').
  has('status', 'active').
  order().by('createdAt', desc).
  limit(20)

11.2 产品顶点 #

gremlin
// 创建产品
g.addV('product').
  property('productId', 'prod_001').
  property('name', 'iPhone 15').
  property('price', 999.99).
  property('category', 'Electronics').
  property(list, 'tags', 'phone').
  property(list, 'tags', 'apple').
  property('stock', 100)

// 查询产品
g.V().hasLabel('product').
  has('category', 'Electronics').
  has('price', inside(500, 1500))

11.3 文档顶点 #

gremlin
// 创建文档
g.addV('document').
  property('docId', 'doc_001').
  property('title', 'Neptune Guide').
  property('content', '...').
  property('author', 'Tom').
  property('createdAt', datetime()).
  property('status', 'published')

// 查询文档
g.V().hasLabel('document').
  has('status', 'published').
  has('createdAt', gt(someDate))

十二、总结 #

顶点操作要点:

操作 Gremlin语法 说明
创建 addV(label) 创建新顶点
查询 V() / has() 查询顶点
更新 property() 更新属性
删除 drop() 删除顶点
遍历 out()/in()/both() 遍历关系

最佳实践:

  1. 为顶点设计合理的标签体系
  2. 使用唯一标识属性
  3. 保持属性命名一致
  4. 使用索引加速查询
  5. 避免顶点属性过多

下一步,让我们学习边与关系!

最后更新:2026-03-27