Dgraph:AI时代的知识图谱引擎
构建智能系统的核心基础设施
核心定位
Dgraph是一款高性能、分布式图数据库,专为处理复杂关系数据而设计。在AI技术爆发式发展的背景下,它成为构建智能系统的核心基础设施。
为什么Dgraph对AI至关重要?
当前AI(尤其是大语言模型LLM)面临的关键挑战:
- 缺乏对信息深层关系的理解
- 难以动态更新知识库
- 无法验证信息的逻辑路径
Dgraph的解决方案
通过知识图谱技术提供:
- 结构化关系表示 - 精准建模实体间的复杂关联(如"用户-行为-商品"网络)
- 实时动态更新 - 支持增量式知识演进,适应快速变化的AI需求
- 可验证推理路径 - 所有结论均可追溯数据源头,满足审计要求
- 多模态语义理解 - 结合语义搜索与向量计算,突破关键词匹配局限
Dgraph的AI原生技术优势
| 能力 | 说明 |
|---|---|
| 多向量嵌入存储 | 同一节点/关系可存储多个AI模型向量,支持跨模型对比与融合 |
| 混合搜索引擎 | 同时支持: - HNSW向量相似度搜索 - 关键词搜索 - 地理空间查询 - 图谱关系遍历 |
| 命名空间隔离 | 为多租户AI应用提供逻辑隔离的数据沙盒(如SaaS平台) |
| 分布式架构 | 线性扩展能力支撑百亿级关联数据 |
典型应用场景:智能推荐系统、生物医药知识发现、健康知识库构建。
企业级AI支持路线图
Dgraph正持续进化以满足AI工业化需求:
- 技术强化 - 优化核心引擎性能,开源v25版本
- LLM深度集成 - 开发自然语言转图谱查询(NL2GraphQL)、语义推理接口
- 生产就绪能力 - 增强监控、RBAC权限控制、SOC2合规性
- 云原生部署 - 按用量计费模式,降低启动成本
Dgraph 核心概念
理解Dgraph的基础架构和核心组件
一、系统架构组件
| 术语 | 说明 |
|---|---|
| Alpha | 数据存储节点,负责: - 存储关系数据(Predicates) - 管理索引 - 通过增加Alpha节点实现横向扩展 |
| Zero | 集群控制节点,负责: - 分配Alpha节点组 - 数据均衡调度 - 事务时间戳管理 - UID分配系统 |
| Badger | 底层存储引擎(Go语言开发): - 高性能键值数据库 - 提供持久化存储层 - 支持快速读写操作 |
二、数据模型
| 术语 | 说明 |
|---|---|
| Node | 业务实体对象: - 通过全局唯一标识符(UID)定位 - 可包含属性值(如姓名) - 与其他节点建立关系 |
| Predicate | 数据最小单元,分为两类: 1. 属性类型:存储字面值(如 name: "Alice")2. 关系类型:连接其他节点(如 knows: <Bob_UID>)
|
| Edge | 节点间连接线(关系可视化表达) |
| Relationship | 具名有向关系: - 可附加属性(Facets)如权重/时间/类型 - 等同于Edge和Predicate的关系类型 |
| Triple | RDF标准数据单元:<Subject> <Predicate> <Object>(如 <Alice> <knows> <Bob>)
|
| UID | 节点全局唯一标识符: - 系统自动生成或显式指定 - 通过 uid属性访问 |
三、查询语言
| 术语 | 说明 |
|---|---|
| DQL | Dgraph原生查询语言: - 基于GraphQL扩展 - 支持数据增删改查 - 比GraphQL表达能力更强 |
| GraphQL | 标准声明式查询语言: - Dgraph自动暴露GraphQL API端点 - 支持部署GraphQL数据模型 |
| Mutation | 数据修改操作: - 包含插入/更新/删除 - 可与Query组合成Upsert操作 |
| Upsert | 查询+修改组合操作: - 实现节点存在性检查 - 确保谓词唯一性 |
四、高级功能
| 术语 | 说明 |
|---|---|
| Lambda | GraphQL解析器: - 用JavaScript编写自定义逻辑 - 操作GraphQL类型/接口/查询(与AWS Lambda无关) |
| Sharding | 分布式架构核心: - 按谓词分片(Predicate-based) - 单个谓词数据存储于同组服务器 |
| gRPC | 高性能通信框架: - 支持Go/C#/Java/JS/Python客户端 - 在事务中执行修改与查询 |
五、工具与标准
| 术语 | 说明 |
|---|---|
| Ratel | 官方GUI工具: - 数据可视化 - 集群管理 - 支持DQL操作 |
| RDF | 语义网标准数据格式: - Dgraph支持RDF/JSON双格式 - 用于数据导入/导出 |
核心特性总结
- 混合数据模型 - 融合属性图(Property Graph)与RDF三元组模型,支持复杂关系建模
- 分布式架构 - 通过Predicate分片实现线性扩展,Zero节点智能调度资源
- 多语言支持 - 官方gRPC客户端覆盖主流开发语言
- 标准化兼容 - 原生支持GraphQL API与RDF数据交换格式
- 实时可扩展 - Lambda机制允许注入自定义业务逻辑
澄清
澄清Dgraph的常见误解与核心概念
核心概念对比
理解Dgraph中几个关键概念的区别和联系,避免混淆。
DQL vs GraphQL
| 特性 | DQL | GraphQL |
|---|---|---|
| 语法风格 | 函数式,基于RDF三元组 | 声明式,类似JSON结构 |
| 查询方式 | func: eq(name, "Alice") |
queryPerson(filter: {name: {eq: "Alice"}}) |
| 复杂查询 | 支持递归、聚合、变量 | 功能相对有限 |
| 适用场景 | 复杂图分析、数据科学 | 前端应用、API开发 |
JSON vs RDF
| 特性 | JSON | RDF |
|---|---|---|
| 结构 | 嵌套对象和数组 | 三元组(subject-predicate-object) |
| 可读性 | 直观易读 | 需要理解RDF概念 |
| 适用场景 | API交换、配置管理 | 知识图谱、语义查询 |
DQL/GQL vs JSON/RDF
重要区别
DQL/GQL是查询语言,JSON/RDF是数据格式 - 这是两个不同层面的概念:
- DQL/GQL:用于查询和操作数据的语言/语法
- JSON/RDF:用于存储和传输数据的格式/结构
| 层面 | DQL/GQL(查询语言) | JSON/RDF(数据格式) |
|---|---|---|
| 性质 | 操作指令:如何查询数据 | 数据结构:如何存储数据 |
| 作用 | 告诉数据库"我要什么" | 告诉数据库"数据长什么样" |
| 关系 | DQL操作RDF格式,GQL操作JSON格式 | RDF是DQL的底层,JSON是GQL的接口 |
| 示例 | func: eq(name, "Alice") |
{"name": "Alice"} |
实际应用关系
# DQL查询RDF格式的数据
{
alice(func: eq(name, "Alice")) {
uid
name
}
}
# 返回JSON格式的结果
{
"alice": [
{
"uid": "0x1",
"name": "Alice"
}
]
}
# GraphQL查询(内部转换为DQL)
query {
queryPerson(filter: { name: { eq: "Alice" } }) {
id
name
}
}
Schema Type vs dgraph.type
| 特性 | Schema Type定义 | dgraph.type赋值 |
|---|---|---|
| 性质 | 蓝图/模板:定义理想结构 | 实例/实现:标记具体节点 |
| 作用 | 规定:"Person应该有哪些字段" | 声明:"这个节点是Person" |
| 用途 | 数据验证、API生成 | 数据查询、类型过滤 |
节点类型:dgraph.type详解
深入理解Dgraph中最重要的概念之一:节点类型系统。
核心理解
类比说明
- 节点 = 实体(人、公司、产品等)
dgraph.type= 标签集合(分类标识)- 就像给物品贴标签,一个物品可以有多个标签
- 回答:"这个节点属于哪些类型?"
实际例子:
Alice可以同时是:Person + Employee + Manager
就像一个人可以同时是:学生 + 员工 + 志愿者
关键价值
| 价值 | 说明 |
|---|---|
| 高效查询 | 通过类型索引快速定位,避免全表扫描 |
| 数据组织 | 为大规模图数据提供结构化分类 |
| Schema集成 | 连接具体数据与抽象模型定义 |
| 权限控制 | 基于类型设置数据访问权限 |
使用方法
基本用法
# 单类型节点
_:alice <dgraph.type> "Person" .
_:alice <name> "Alice Johnson" .
# 多类型节点
_:bob <dgraph.type> "Person" .
_:bob <dgraph.type> "Employee" .
_:bob <dgraph.type> "Manager" .
_:bob <name> "Bob Smith" .
查询操作
# 按类型查询
{
persons(func: type(Person)) {
uid
name
}
}
# 多类型查询
{
employees(func: type(Person, Employee)) {
uid
name
dgraph.type
}
}
重要澄清
Dgraph不支持类型继承
关键事实:Dgraph的类型系统是扁平化的,不支持真正的继承关系。
- ❌ 没有父类-子类关系
- ❌ 没有属性继承
- ✅ 支持多类型标签
- ✅ 通过标签组合模拟层次关系
常见误区澄清
澄清关于Dgraph的常见误解,避免踩坑。
误区1:可以创建自定义类型谓语
❌ 错误做法:
_:alice <myType> "Person" .
_:alice <nodeType> "Employee" .
✅ 正确做法:
_:alice <dgraph.type> "Person" .
_:alice <dgraph.type> "Employee" .
事实:自定义谓语无法与Dgraph的类型系统和GraphQL集成协同工作。
误区2:不设置dgraph.type也可以
❌ 没有dgraph.type的节点:
_:alice <name> "Alice" .
_:alice <age> "30" .
查询时无法找到:
{
persons(func: type(Person)) {
name # 结果为空
}
}
事实:没有dgraph.type的节点无法参与基于类型的查询和操作。
误区3:Schema Type和dgraph.type是同一个东西
事实:Schema中的type是蓝图,dgraph.type是具体实现,两者需要配合但并非同一概念。
- Schema Type:定义数据结构和API接口
- dgraph.type:标记具体节点的类型归属
- 必须一致:Schema中定义的类型名必须与dgraph.type的值匹配
误区4:一个节点只能有一个类型
❌ 错误理解:认为每个节点只能属于一个类型
✅ 正确理解:一个节点可以有多个类型标签
# ✅ 正确:一个节点可以有多个类型
_:alice <dgraph.type> "Person" .
_:alice <dgraph.type> "Employee" .
_:alice <dgraph.type> "Manager" .
_:alice <name> "Alice" .
# 查询时可以看到所有类型
{
alice(func: eq(name, "Alice")) {
uid
name
dgraph.type # 返回: ["Person", "Employee", "Manager"]
}
}
实际价值:多类型标签让节点可以同时扮演多个角色,更灵活地建模现实世界。
误区5:Dgraph支持类型继承
❌ 错误理解:认为Employee可以"继承"Person的所有属性
✅ 正确理解:Dgraph不支持继承,只能通过多类型标签模拟
# ❌ 错误:以为有继承关系
# Employee "继承" 自 Person
# ✅ 正确:通过多类型标签模拟
_:bob <dgraph.type> "Person" .
_:bob <dgraph.type> "Employee" .
_:bob <name> "Bob" . # Person属性
_:bob <employeeId> "EMP1" . # Employee属性
# 查询所有Person(包括Employee)
{
allPersons(func: type(Person)) {
uid
name
employeeId # Employee节点有此字段,纯Person节点为null
}
}
关键区别:没有自动的属性继承,需要手动为每个节点分配所有相关类型标签。
误区6:图数据库只适合社交网络
❌ 错误理解:认为图数据库只能用于朋友关系、社交网络
✅ 正确理解:适用于任何有复杂关系的场景
| 应用场景 | 关系类型 | 实际价值 |
|---|---|---|
| 电商平台 | 用户-商品-订单-评价 | 推荐算法、用户行为分析 |
| 金融系统 | 账户-交易-风险-合规 | 反欺诈、风险评估 |
| 知识图谱 | 实体-概念-关系-属性 | 智能问答、知识发现 |
| 物联网 | 设备-传感器-事件-位置 | 设备管理、异常检测 |
| 生物信息 | 基因-蛋白质-疾病-药物 | 药物发现、疾病研究 |
核心优势:图数据库擅长处理多对多关系、复杂查询和关系分析,不仅限于社交网络。
误区7:图数据库性能不如关系数据库
❌ 错误理解:认为图数据库在所有场景下都比关系数据库慢
✅ 正确理解:在关系密集型查询中,图数据库性能更优
# 图数据库:O(1)关系查找
{
alice(func: eq(name, "Alice")) {
friend {
friend {
name # 2度朋友,高效查询
}
}
}
}
# 关系数据库:需要多次JOIN
SELECT f2.name
FROM person p1
JOIN friendship f1 ON p1.id = f1.person1_id
JOIN person p2 ON f1.person2_id = p2.id
JOIN friendship f2 ON p2.id = f2.person1_id
WHERE p1.name = 'Alice'
性能特点:图数据库在关系遍历、多跳查询、图算法方面性能优异,但在简单CRUD操作上可能不如关系数据库。
误区8:Dgraph只能存储图数据
❌ 错误理解:认为Dgraph只能存储节点和边的关系数据
✅ 正确理解:Dgraph可以存储任何类型的数据
# 可以存储复杂嵌套结构
_:document <dgraph.type> "Document" .
_:document <title> "技术文档" .
_:document <content> "这是一份详细的技术文档..." .
_:document <metadata> '{"author": "Alice", "version": "1.0"}' .
_:document <tags> "技术" .
_:document <tags> "文档" .
_:document <tags> "指南" .
# 支持多种数据类型
_:product <dgraph.type> "Product" .
_:product <name> "智能手机" .
_:product <price> "2999.99" .
_:product <inStock> "true" .
_:product <releaseDate> "2024-01-15" .
_:product <specifications> '{"ram": "8GB", "storage": "256GB"}' .
支持的数据类型:字符串、数字、布尔值、日期时间、JSON对象、地理空间数据、全文搜索等。
最佳实践
遵循这些实践,确保正确使用Dgraph。
必须遵循的实践
| 实践 | 说明 | 重要性 |
|---|---|---|
| 始终使用dgraph.type | 不要尝试创建自定义谓语来替代 | ⚠️ 必须 |
| 预先规划类型系统 | 在设计阶段规划好类型结构 | ⚠️ 必须 |
| 为dgraph.type建立索引 | 否则无法高效查询 | ⚠️ 必须 |
| 保持一致性 | Schema定义与实际使用保持一致 | ⚠️ 必须 |
| 命名规范 | 类型名使用PascalCase | ✅ 推荐 |
思维和原则
图数据库的哲学思维与设计原则
哲学思维:世界即关系,关系即意义
Dgraph 的哲学并非源于对传统数据库或其它技术的否定,而是源于一种 对世界本质的不同认知。
核心思想
- 世界是由 实体及其间无限的关系 构成的
- 理解世界的最佳方式,不是先定义范畴再填充数据,而是 先记录一切可观察的事实,让意义和结构从中"涌现"(Emerge)
- 这是一种 自下而上、基于实践和观察的认识论,与"自上而下"、基于理论和分类的认识论形成互补
- Dgraph 正是这种哲学在数据领域的实践体现
第一性原理:关系的原生性
The Primacy of Relationships
核心思想
- 关系不是数据的附属品,而是与数据原子同等重要的基础组成部分
- 在 Dgraph 中,一条关系(边)和一条属性(谓词)在存储和处理的层面上是 同构的
- 这意味着,连接两个节点的"关系"本身,就是一个独立、可检索、可计算的"一等公民"
深层解读
- 打破了"实体为主,关系为辅"的传统数据观
- 世界不是孤立的点的集合,而是一张交织的网
- 任何一个点(实体)的意义和价值,完全由它与其它无数点的连接方式(关系)来定义
- 没有关系,实体就近乎于不存在
方法论:平铺、标记与涌现
Flatten, Label, and Emerge
1. 平铺(Flatten)
- 放弃预先设计复杂、静态的层级结构(如多表关联、严格分类)
- 将所有已知的事实以最直接的方式"平铺"为三元组
# 三元组示例
(人物A) - (居住在) - (城市B)
(人物A) - (喜欢) - (电影C)
(电影C) - (的类型是) - (科幻)
无需额外设计"关系表",只是陈述事实。
2. 标记(Label)
- "谓词"(Predicate)即是标签
- 可以是属性(姓名、年龄)、关系(朋友、创作)、甚至类别(科幻、爵士乐)
- 谓词本身也是数据,可以随时新增,不破坏原有结构
- Schema 会随着事实积累而自然生长
3. 涌现(Emerge)
- 不必预先知道所有问题的答案
- 只需持续记录事实和标签
- 当数据累积到一定程度,使用 DQL/GraphQL 查询时,隐藏的模式、关联与洞察会自然"浮现"
- 例如:你可能会发现"喜欢某类音乐的人,常住在某类城市"
- 这不是事先假设的,而是从数据中读出来的
Dgraph 的实现:为涌现而生的引擎
1. 分布式图灵机
- 所有数据视为三元组,分布式存储
- 查询时,像一台并行图灵机在巨图上遍历,让复杂的深度关联查询成为可能
2. 灵活的模式(Schema)
- 支持 Schema-less 写入,先自由贴标签,再引入模式确认规律
- 模式不是限制,而是对"已涌现规律"的总结与固化
3. GraphQL/DQL 查询语言
- 查询即探索路径:从一个点出发,沿关系逐步扩展、过滤、聚合
- 查询过程本身就是数据探索的模拟
设计原则
| 原则 | 说明 |
|---|---|
| 三元组原则 | 一切都是 (subject → predicate → object) |
| 全局命名原则 | UID、谓语全局唯一 |
| 灵活建模原则 | Schema 可选,允许演化 |
| 关系优先原则 | 价值来自多跳关系查询 |
| 类型即接口 | Type 用于对外暴露 API,而非约束本体 |
| 演化原则 | 数据模式随着认知成长,不必一次到位 |
| 统一接口原则 | DQL(底层灵活) + GraphQL(接口友好) |
总结:数据的有机体
Dgraph 的哲学鼓励我们把数据库视为 一个生长的有机体,而不是一个静态的建筑:
| 对比 | 传统数据库(建筑) | Dgraph(有机体) |
|---|---|---|
| 设计理念 | 依赖蓝图(ER 图),结构一旦确定,修改代价极高 | 从简单三元组开始,随着环境输入(新数据)不断演化 |
| 发展方式 | 静态结构,需要重新设计才能扩展 | 动态生长,最终形成复杂、智慧、充满内在联系的整体 |
使用 Dgraph 的最佳方式
- 立即开始,不必等完美 schema
- 记录一切事实,拥抱不确定性
- 让模式和意义自然"涌现"
- 把它当作 思想的放大镜,帮助你发现超越逻辑推演的复杂真理
一句话总结
Dgraph 的哲学是 关系原生、事实平铺、意义涌现;它既是数据库,也是一个不断成长的知识有机体。
部署方式选择指南
根据数据规模、技术能力、预算和控制需求选择最适合的部署方式
部署决策关键因素
当迁移到自托管Dgraph时,您的部署选择取决于几个关键因素:数据规模、团队技术能力、预算限制和控制需求。以下是这些因素如何影响部署决策的详细分析:
1. 数据规模考量
数据规模是选择部署方式的首要因素:
| 数据规模 | 推荐部署方式 | 说明 |
|---|---|---|
| < 100GB | Docker Compose 或 Linux | 小规模数据,单机部署即可满足需求 |
| 100GB – 1TB | Kubernetes 或 Linux | 中等规模,需要考虑扩展性和高可用性 |
| > 1TB | Kubernetes(必须) | 大规模数据,必须使用分布式架构 |
2. 团队技术能力因素
团队的技术经验和专业知识直接影响部署方式的选择:
| 团队经验水平 | 推荐部署方式 | 优势 |
|---|---|---|
| Kubernetes 经验丰富 | Kubernetes(推荐) | 充分利用K8s的自动化能力 |
| Kubernetes 经验有限 | Docker Compose 或 Linux | 更易上手,降低学习成本 |
3. 预算限制
预算策略决定了您能承受的基础设施和管理成本:
| 预算策略 | 推荐部署方式 | 特点 |
|---|---|---|
| 成本优化型 | Linux(最经济) | 直接部署在裸金属服务器,无额外管理开销 |
| 平衡型 | Docker Compose(折中选择) | 容器化部署,便于管理但成本可控 |
| 企业级 | Kubernetes(企业级功能) | 支持自动扩缩容、高可用性,但成本较高 |
4. 控制需求
对基础设施的控制程度影响部署方式的选择:
| 控制级别 | 推荐部署方式 | 特点 |
|---|---|---|
| 最大控制权 | Linux(完全掌控环境) | 适合需要深度定制和优化的团队 |
| 托管基础设施 | Kubernetes(自动化管理能力) | 适合希望减少运维负担的企业 |
5. 可用部署方法对比
不同部署方式的特点和适用场景:
| 部署方式 | 适用场景 | 优势 | 注意事项 |
|---|---|---|---|
| Kubernetes | 大规模部署、企业环境、具备K8s专业知识的团队 | 自动扩缩容、高可用性、服务发现 | 学习曲线陡峭、运维复杂度高 |
| Docker Compose | 开发、测试环境,或小型生产负载 | 快速部署、易于管理、成本可控 | 扩展性有限、单点故障风险 |
| Linux | 预算有限、需要完全控制基础设施的团队 | 成本最低、完全控制、性能最优 | 手动配置、运维复杂度高 |
6. 部署决策流程图
使用以下决策树来帮助选择最适合的部署方式:
决策流程
- 数据规模评估
- 如果 < 100GB → 考虑 Docker Compose 或 Linux
- 如果 100GB - 1TB → 考虑 Kubernetes 或 Linux
- 如果 > 1TB → 必须使用 Kubernetes
- 技术能力评估
- 如果 K8s 经验丰富 → 优先选择 Kubernetes
- 如果 K8s 经验有限 → 选择 Docker Compose 或 Linux
- 预算控制评估
- 如果成本敏感 → 选择 Linux
- 如果平衡型 → 选择 Docker Compose
- 如果企业级 → 选择 Kubernetes
7. 渐进式迁移策略
如果团队缺乏Kubernetes经验但需要扩展性,建议采用渐进式迁移策略:
第一阶段:原型验证
使用 Docker Compose 快速搭建环境,验证业务逻辑和性能需求。
第二阶段:学习提升
团队学习 Kubernetes 基础知识,在测试环境中进行小规模部署。
第三阶段:生产迁移
逐步将生产环境迁移到 Kubernetes,确保平滑过渡。
总结建议
开发/测试环境
推荐:Docker Compose
原因:快速搭建,便于迭代
中小规模生产(<1TB)
推荐:Linux(低成本)或 Kubernetes(如需扩展性)
原因:平衡成本和功能需求
大规模企业级(>1TB)
推荐:必须使用 Kubernetes
原因:确保高可用和自动化管理
重要提醒
注:如果团队缺乏Kubernetes经验但需要扩展性,建议先采用Docker Compose进行原型验证,再逐步迁移到Kubernetes。
Docker部署
快速搭建Dgraph开发和生产环境
环境准备
确保您的系统已安装Docker和Docker Compose:
# 检查Docker版本
docker --version
docker-compose --version
# 确保Docker服务正在运行
docker info
版本选择
Dgraph提供多个版本,根据您的需求选择合适的版本:
- V25版本:最新预览版,支持MCP功能
- V24版本:稳定版本,生产环境推荐
- Latest版本:最新稳定版本
V25版本配置(推荐开发环境)
创建docker-compose-v25.yml文件:
version: "3.8"
services:
zero:
container_name: zero
image: Dgraph/Dgraph:v25.0.0-preview6
volumes:
- /opt/Dgraph:/Dgraph
ports:
- 5080:5080
- 6080:6080
restart: on-failure
command: Dgraph zero --my=zero:5080
networks:
- Dgraph-network
alpha:
container_name: alpha
image: Dgraph/Dgraph:v25.0.0-preview6
volumes:
- /opt/Dgraph:/Dgraph
ports:
- 8080:8080
- 9080:9080
restart: on-failure
command: Dgraph alpha --my=alpha:7080 --zero=zero:5080 --mcp --security whitelist=0.0.0.0/0
networks:
- Dgraph-network
ratel:
container_name: ratel
image: Dgraph/ratel:latest
ports:
- 8000:8000
networks:
- Dgraph-network
networks:
Dgraph-network:
driver: bridge
V25版本特性
- 支持MCP(Model Context Protocol)功能
- 增强的安全性和性能
- 改进的GraphQL支持
- 注意:这是预览版本,不建议在生产环境使用
V24版本配置(生产环境推荐)
创建docker-compose-v24.yml文件:
version: "3.2"
services:
zero:
image: Dgraph/Dgraph:latest
volumes:
- /opt/Dgraph:/Dgraph
ports:
- 5080:5080
- 6080:6080
restart: on-failure
command: Dgraph zero --my=zero:5080
alpha:
image: Dgraph/Dgraph:latest
volumes:
- /opt/Dgraph:/Dgraph
ports:
- 8080:8080
- 9080:9080
restart: on-failure
command: Dgraph alpha --my=alpha:7080 --zero=zero:5080 --security whitelist=0.0.0.0/0
ratel:
image: Dgraph/ratel:latest
ports:
- 8000:8000
restart: on-failure
V24版本优势
- 稳定可靠,经过充分测试
- 生产环境验证
- 完整的文档和社区支持
- 企业级功能支持
启动服务
在包含配置文件的目录中运行:
# 启动V25版本服务
docker-compose -f docker-compose-v25.yml up -d
# 启动V24版本服务
docker-compose -f docker-compose-v24.yml up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 停止服务
docker-compose down
验证部署
服务启动后,可以通过以下方式验证:
| 服务 | 端点 | 说明 |
|---|---|---|
| GraphQL API | http://localhost:8080/graphql | GraphQL查询和变更接口 |
| DQL端点 | http://localhost:8080/query | Dgraph查询语言接口 |
| Ratel工具 | http://localhost:8000 | 图形化管理界面 |
| HTTP API | http://localhost:9080 | HTTP JSON格式接口 |
| MCP端点(V25) | http://localhost:8080/mcp/sse | AI助手集成接口 |
组件说明
Dgraph集群由三个核心组件组成:
| 组件 | 功能说明 | 端口 |
|---|---|---|
| Zero | 集群管理节点,负责元数据管理、节点协调、分片分配 | 5080(RPC), 6080(HTTP) |
| Alpha | 数据存储节点,执行查询、更新数据、管理存储 | 7080(Live Query), 8080(GraphQL), 9080(HTTP), 9180(gRPC) |
| Ratel | 图形用户界面,提供友好的数据管理和查询界面 | 8000(Web UI) |
MCP功能配置(V25版本)
V25版本支持MCP(Model Context Protocol),可以集成AI助手:
# 使用 --mcp 启动 Dgraph Alpha
Dgraph alpha --my=localhost:7080 --zero=localhost:5080 --mcp
# 启用两个MCP端点:
# 完全访问:http://localhost:8080/mcp/sse
# 只读访问:http://localhost:8080/mcp-ro/sse
AI助手配置示例
为本地Dgraph配置AI助手(如Claude Desktop):
{
"mcpServers": {
"Dgraph-local": {
"command": "npx",
"args": ["mcp-remote", "http://localhost:8080/mcp/sse"]
},
"Dgraph-local-readonly": {
"command": "npx",
"args": ["mcp-remote", "http://localhost:8080/mcp-ro/sse"]
}
}
}
常用管理命令
日常运维和管理命令:
# 查看容器状态
docker ps -a
# 查看容器日志
docker logs -f alpha
docker logs -f zero
docker logs -f ratel
# 进入容器
docker exec -it alpha bash
docker exec -it zero bash
# 备份数据
docker exec alpha Dgraph backup --alpha=localhost:9080 --destination=/Dgraph/backup
# 恢复数据
docker exec alpha Dgraph restore --alpha=localhost:9080 --backup=/Dgraph/backup
# 查看集群状态
curl http://localhost:8080/state
注意事项
- 数据持久化:确保挂载的目录有适当的权限
- 网络安全:生产环境建议配置防火墙和访问控制
- 资源限制:根据数据量调整内存和CPU限制
- 备份策略:定期备份数据,测试恢复流程
- 监控告警:配置监控系统,及时发现异常
部署总结
- 版本选择 - V25用于开发测试,V24用于生产环境
- 组件配置 - Zero、Alpha、Ratel三个核心组件
- 端口管理 - 不同服务使用不同端口,避免冲突
- MCP支持 - V25版本支持AI助手集成
- 运维管理 - 完善的监控、备份、恢复策略
Go客户端
使用Go语言连接和操作Dgraph - 支持v2 API
安装依赖
在Go项目中添加Dgraph客户端依赖:
// 传统v1 API(兼容性)
go get github.com/Dgraph-io/dgo/v210
go get github.com/Dgraph-io/dgo/v210/protos/api
// 新版v2 API(推荐,版本25+)
go get github.com/Dgraph-io/dgo/v250
版本说明
v2 API特性:版本25引入v2 API,提供更简化的客户端创建和DQL执行功能,当前支持dgo/v250包。
建立连接
Dgraph v2 API支持多种连接方式:
基础连接方式
dgo包支持通过连接字符串连接Dgraph集群,格式为:Dgraph://host:port?arguments
| 参数 | 可选值 | 说明 |
|---|---|---|
| bearertoken | <token> | 访问令牌 |
| sslmode | disable/require/verify-ca | TLS模式(默认disable),verify-ca需配置有效CA证书 |
package main
import (
"context"
"log"
"github.com/Dgraph-io/dgo/v250"
)
func main() {
// 连接非TLS集群
client, err := dgo.Open("Dgraph://localhost:9080")
if err != nil {
panic(err)
}
defer client.Close()
log.Println("成功连接到Dgraph!")
}
高级客户端配置
根据需求选择不同的客户端配置:
单节点客户端
import (
"github.com/Dgraph-io/dgo/v250"
"google.golang.org/grpc/credentials/insecure"
)
client, err := dgo.NewClient("localhost:9080",
dgo.WithGrpcOption(grpc.WithTransportCredentials(insecure.NewCredentials())),
)
if err != nil {
panic(err)
}
defer client.Close()
多节点负载均衡客户端
client, err := dgo.NewRoundRobinClient([]string{
"localhost:9181",
"localhost:9182",
"localhost:9183",
}, dgo.WithGrpcOption(grpc.WithTransportCredentials(insecure.NewCredentials())))
if err != nil {
panic(err)
}
defer client.Close()
连接Hypermode Graph
Hypermode集群自动处理负载均衡,支持两种连接方式:
通过连接字符串
client, err := dgo.Open("Dgraph://.hypermode.host?sslmode=verify-ca&bearertoken=")
if err != nil {
panic(err)
}
defer client.Close()
通过NewClient
client, err := dgo.NewClient(".hypermode.host:443",
dgo.WithBearerToken(""),
dgo.WithSystemCertPool(), // 使用系统证书池
)
if err != nil {
panic(err)
}
defer client.Close()
数据操作
v2 API简化了DQL执行流程,统一使用RunDQL方法:
设置Schema
sch := `
name: string @index(exact) .
email: string @index(exact) @unique .
age: int .
`
err := client.SetSchema(context.TODO(), dgo.RootNamespace, sch)
if err != nil {
panic(err)
}
插入数据(Mutation)
mutationDQL := `{
set {
_:alice "Alice" .
_:alice "alice@example.com" .
_:alice "29" .
}
}`
resp, err := client.RunDQL(context.TODO(), dgo.RootNamespace, mutationDQL)
if err != nil {
panic(err)
}
fmt.Printf("生成UID映射: %+v\n", resp.BlankUids)
查询数据(Query)
支持多种查询方式和选项:
基础查询
queryDQL := `{
alice(func: eq(name, "Alice")) {
name
email
age
}
}`
resp, err := client.RunDQL(context.TODO(), dgo.RootNamespace, queryDQL)
if err != nil {
panic(err)
}
fmt.Printf("查询结果: %s\n", resp.QueryResult)
带变量的查询
queryDQL := `query Alice($name: string) {
alice(func: eq(name, $name)) {
name
email
age
}
}`
vars := map[string]string{"$name": "Alice"}
resp, err := client.RunDQLWithVars(context.TODO(), dgo.RootNamespace, queryDQL, vars)
if err != nil {
panic(err)
}
只读查询(ReadOnly)
resp, err := client.RunDQL(context.TODO(), dgo.RootNamespace, queryDQL, dgo.WithReadOnly())
if err != nil {
panic(err)
}
RDF格式返回
import "github.com/Dgraph-io/dgo/v250/protos/api_v2"
resp, err := client.RunDQL(context.TODO(), dgo.RootNamespace, queryDQL,
dgo.WithResponseFormat(api_v2.RespFormat_RDF))
if err != nil {
panic(err)
}
更新或插入(Upsert)
支持基础Upsert和条件Upsert操作:
基础Upsert
upsertQuery := `upsert {
query { user as var(func: eq(email, "alice@example.com")) }
mutation {
set {
uid(user) "30" .
uid(user) "Alice Sayum" .
}
}
}`
resp, err := client.RunDQL(context.TODO(), dgo.RootNamespace, upsertQuery)
if err != nil {
panic(err)
}
条件Upsert(@if指令)
upsertQuery := `upsert {
query { user as var(func: eq(email, "alice@example.com")) }
mutation @if(eq(len(user), 1)) {
set {
uid(user) "30" .
uid(user) "Alice Sayum" .
}
}
}`
resp, err := client.RunDQL(context.TODO(), dgo.RootNamespace, upsertQuery)
if err != nil {
panic(err)
}
数据清理
清理和重置数据:
清空所有数据
err := client.DropAllNamespaces(context.TODO())
if err != nil {
panic(err)
}
安全配置
生产环境的安全建议:
安全配置要点
-
启用TLS:生产环境务必启用
sslmode=verify-ca - 访问令牌:配置
bearertoken进行身份验证 - CA证书:确保集群配置有效的CA证书
- 网络隔离:限制客户端访问的网络范围
完整示例
一个完整的Go客户端使用示例:
package main
import (
"context"
"fmt"
"log"
"github.com/Dgraph-io/dgo/v250"
)
func main() {
// 1. 建立连接
client, err := dgo.Open("Dgraph://localhost:9080")
if err != nil {
log.Fatal("连接失败:", err)
}
defer client.Close()
ctx := context.Background()
// 2. 设置Schema
schema := `
name: string @index(exact) .
email: string @index(exact) @unique .
age: int .
`
if err := client.SetSchema(ctx, dgo.RootNamespace, schema); err != nil {
log.Fatal("设置Schema失败:", err)
}
// 3. 插入数据
mutation := `{
set {
_:alice "Alice" .
_:alice "alice@example.com" .
_:alice "29" .
}
}`
resp, err := client.RunDQL(ctx, dgo.RootNamespace, mutation)
if err != nil {
log.Fatal("插入数据失败:", err)
}
fmt.Printf("插入成功,UID映射: %+v\n", resp.BlankUids)
// 4. 查询数据
query := `{
alice(func: eq(name, "Alice")) {
name
email
age
}
}`
queryResp, err := client.RunDQL(ctx, dgo.RootNamespace, query)
if err != nil {
log.Fatal("查询失败:", err)
}
fmt.Printf("查询结果: %s\n", queryResp.QueryResult)
}
关键特性总结
- v2 API特性 - 简化了DQL执行流程,统一使用RunDQL方法处理查询和变更
- 多种连接方式 - 支持连接字符串、单节点、多节点负载均衡
- Hypermode集成 - 自动负载均衡,适合多节点生产环境
- 完整数据操作 - 支持Schema设置、增删改查、Upsert等操作
- 安全配置 - 支持TLS、访问令牌、CA证书等安全特性
重要提醒
注:所有代码示例需处理错误(if err != nil),此处为简洁省略。生产环境务必启用sslmode=verify-ca和bearertoken。
GraphiQL
使用GraphiQL进行GraphQL查询和开发
什么是GraphiQL
GraphiQL是一个用于测试GraphQL查询的交互式开发环境,提供语法高亮、自动补全、实时错误提示和查询历史记录。它是GraphQL开发者的必备工具。
获取GraphiQL
下载独立的GraphiQL文件,可以离线使用,更灵活:
下载GraphiQL
点击下方按钮下载 view.html 文件
使用步骤
- 下载
view.zip文件到本地 - 解压zip文件,获得
view.html - 修改
view.html中的url配置 - 用浏览器直接打开即可使用
优势特点
- 非常简单:只需修改URL部分,就可以使用浏览器直接打开使用了!
- 离线可用:本地文件,不依赖网络连接
- 完全控制:可以自定义配置和修改
- 便携性强:文件可以复制到任何地方使用
配置GraphiQL
修改 view.html 文件中的配置:
修改GraphQL端点
// 找到这一行并修改URL
const fetcher = createGraphiQLFetcher({
url: 'http://localhost:8080/graphql', // 修改为您的Dgraph GraphQL端点
});
常见配置示例
| 部署类型 | URL配置 | 说明 |
|---|---|---|
| 本地Docker | http://localhost:8080/graphql |
标准Docker部署端口 |
| 本地独立部署 | http://localhost:9080/graphql |
独立部署的HTTP端口 |
| 远程服务器 | http://your-server:8080/graphql |
替换为实际服务器地址 |
| HTTPS服务 | https://your-domain.com/graphql |
生产环境HTTPS配置 |
使用GraphiQL
配置完成后,用浏览器打开 view.html 文件即可开始使用:
基本操作步骤
- 打开文件:用浏览器打开下载的
view.html文件 - 验证连接:确认右上角显示连接状态
- 开始查询:在左侧编辑器中编写GraphQL查询
- 执行查询:点击播放按钮或按
Ctrl+Enter执行 - 查看结果:右侧面板显示查询结果
基本查询示例
在GraphiQL中尝试以下查询:
查询所有人员
query {
queryPerson {
id
name
age
friend {
name
age
}
}
}
条件查询
query {
queryPerson(filter: { age: { ge: 25 } }) {
id
name
age
email
}
}
插入数据
mutation {
addPerson(input: {
name: "张三"
age: 30
email: "zhangsan@example.com"
}) {
person {
id
name
age
email
}
}
}
GraphiQL功能特性
GraphiQL提供丰富的开发功能:
语法高亮
GraphQL查询语法彩色显示,提高代码可读性
自动补全
智能提示字段名、类型和参数,减少输入错误
实时验证
即时检查语法错误和类型不匹配问题
查询历史
保存和重用之前的查询语句
文档浏览器
右侧面板显示Schema文档,便于了解可用字段
变量支持
支持查询变量,便于参数化查询
常见问题解决
使用过程中可能遇到的问题和解决方案:
| 问题 | 解决方案 |
|---|---|
| 无法连接到Dgraph | 检查URL配置、网络连接、Dgraph服务状态 |
| 查询返回错误 | 检查查询语法、字段名是否正确、Schema是否已设置 |
| 浏览器显示空白 | 检查JavaScript控制台错误、网络请求是否成功 |
| 字段不显示 | 确认Schema中已定义该字段、检查字段权限 |
使用总结
- 下载配置 - 下载view.html文件,修改URL配置
- 简单使用 - 用浏览器直接打开即可使用
- 功能丰富 - 语法高亮、自动补全、实时验证
- 开发友好 - 查询历史、文档浏览、变量支持
- 离线可用 - 本地文件,不依赖网络连接
快速开始
三步搞定:下载文件 → 修改URL → 浏览器打开,就是这么简单!
Postman
使用Postman测试Dgraph API
配置请求
在Postman中配置Dgraph请求:
- URL:http://localhost:8080/graphql
- Method:POST
- Headers:Content-Type: application/json
管理接口
Dgraph还提供了管理接口用于系统监控和配置:
- 管理界面:http://localhost:8080/admin
- 功能:集群状态监控、性能指标、健康检查
- 用途:系统管理、故障排查、性能调优
说明:管理接口提供了Dgraph集群的实时监控信息,包括节点状态、内存使用、查询性能等关键指标,是运维人员的重要工具。
请求体示例
GraphQL查询请求体:
{
"query": "query { queryPerson { id name age } }",
"variables": {}
}
DQL语法
Dgraph原生查询语言完整指南
关键词
DQL的核心关键词定义了查询和操作的基本结构:
核心关键词
| 关键词 | 用途 | 示例 |
|---|---|---|
query |
查询数据 | query { user(func: has(name)) {...} } |
mutation |
修改数据 | mutation { set { _:a <name> "Alice" . } } |
schema |
定义结构 | schema { name: string @index(term) . } |
type |
定义节点类型 | type User { name, age, friend } |
func |
定义查询函数 | user(func: eq(name, "Alice")) {...} |
var |
变量块 | var(func: has(name)) { friends as friend } |
辅助关键词
| 关键词 | 用途 | 示例 |
|---|---|---|
expand |
展开所有字段 | expand(_all_) |
has |
判断属性存在 | func: has(email) |
uid |
指定 UID | func: uid(0x1, 0x2) |
val |
取变量值 | val(friends) |
math |
数学计算 | math(age + 1) |
名称规则
Dgraph 对谓词类型名称(谓词标识符)、节点类型名称(节点标识符)和变量名称有特定的命名规范:
基本规则
核心要点
- 字母数字组合:任何字母数字组合的谓词名称都是允许的
- 国际化支持:支持国际化资源标识符(IRI)
- 保留命名空间:不能定义以
dgraph.开头的类型或谓词
# ✅ 有效的谓词名称
name: string .
age: int .
user_name: string .
user123: string .
<姓名>: string . # 中文谓词
<user-name>: string . # 带连字符
# ❌ 无效的类型定义
dgraph.Student: string . # 错误:不能以 dgraph. 开头
特殊字符规则
| 字符类型 | 字符列表 | 使用规则 | 示例 |
|---|---|---|---|
| 支持的特殊字符 | ][&*()_-+=!#$% |
允许作为前缀或后缀 | user_name, test-123 |
| 不支持的特殊字符 | ^}|{`\~ |
完全不允许使用 | user^name ❌ |
| @ 后缀 | @ |
不限制使用,但会被忽略 | name@en → name |
实际示例
# ✅ 有效的命名示例
user_name: string @index(term) .
user-age: int @index(int) .
user_email: string @index(exact) .
user_123: string .
user.name: string . # 点号是允许的
user@domain: string . # @ 会被忽略,实际是 userdomain
<用户姓名>: string . # 中文名称
<user-name>: string . # 带连字符
# ❌ 无效的命名示例
^username: string . # 错误:^ 不被支持
user}name: string . # 错误:} 不被支持
{username: string . # 错误:{ 不被支持
`username: string . # 错误:` 不被支持
\username: string . # 错误:\ 不被支持
~username: string . # 错误:~ 不被支持
dgraph.user: string . # 错误:dgraph. 是保留命名空间
国际化资源标识符(IRI)
# IRI 格式的谓词名称
<http://example.org/name>: string .
<https://schema.org/name>: string .
<urn:uuid:123e4567-e89b-12d3-a456-426614174000>: string .
# 使用 IRI 谓词
{
set {
_:user <http://example.org/name> "Alice" .
_:user <https://schema.org/name> "Alice Smith" .
}
}
变量
DQL中的变量用于标识节点、边和存储查询结果:
UID类型
| 类型 | 格式 | 说明 | 示例 |
|---|---|---|---|
| 永久 UID | <0x123> |
系统分配的永久标识符 | <0x1> |
| 临时 Blank Node | _:a |
临时标识符,用于创建新节点 | _:alice |
别名和变量
{
# 给返回结果字段命名
user(func: eq(name, "Alice")) {
uid
name
age
friends: friend { # 别名
name
}
}
# var 变量保存查询结果
var(func: has(name)) {
friends as friend # 保存朋友关系
}
# 使用变量
aliceFriends(func: uid(friends)) {
name
age
}
}
类型系统
Dgraph支持多种数据类型和关系类型:
标量类型
| 类型 | 说明 | 示例 |
|---|---|---|
string |
字符串 | "Alice" |
int |
整数 | 25 |
float |
浮点数 | 3.14 |
bool |
布尔值 | true |
dateTime |
日期时间 | "2024-01-15T10:30:00Z" |
geo |
地理位置 | {"type":"Point","coordinates":[116.4,39.9]} |
password |
密码(加密存储) | "secret123" |
关系类型
# Schema 声明
name: string @index(term) . # 属性
friend: [uid] @reverse . # 多关系
worksFor: uid @reverse . # 单关系
location: geo @index(geo) . # 地理位置
# 节点类型定义
type User {
name
age
friend
worksFor
}
系统保留类型
dgraph.type
dgraph.type 是系统保留的谓词,用于给节点打类型标签:
mutation {
set {
_:alice <name> "Alice" .
_:alice <dgraph.type> "User" .
}
}
函数库
DQL提供丰富的内置函数用于查询和计算:
比较函数
| 函数 | 说明 | 示例 |
|---|---|---|
eq() |
等于 | eq(name, "Alice") |
lt() |
小于 | lt(age, 18) |
gt() |
大于 | gt(age, 65) |
le() |
小于等于 | le(age, 18) |
ge() |
大于等于 | ge(age, 18) |
集合函数
| 函数 | 说明 | 示例 |
|---|---|---|
uid() |
按UID查询 | uid(0x1, 0x2) |
uid_in() |
UID在集合中 | uid_in(friend, 0x1, 0x2) |
between() |
区间查询 | between(age, 18, 65) |
全文搜索函数
| 函数 | 说明 | 示例 |
|---|---|---|
allofterms() |
包含所有关键词 | allofterms(name, "Alice Bob") |
anyofterms() |
包含任一关键词 | anyofterms(name, "Alice Bob") |
anyoftext() |
全文搜索 | anyoftext(description, "machine learning") |
regexp() |
正则匹配 | regexp(name, /^A.*/) |
聚合函数
{
stats(func: has(age)) {
count(uid) # 计数
sum(age) # 求和
avg(age) # 平均值
min(age) # 最小值
max(age) # 最大值
}
}
数学/值函数
{
users(func: has(age)) {
name
age
nextYear: math(age + 1) # 数学计算
friendsCount: count(friend) # 朋友数量
}
}
运算符
DQL支持多种运算符进行逻辑和比较操作:
逻辑运算符
{
# AND 逻辑
adults(func: has(age)) @filter(ge(age, 18) AND le(age, 65)) {
name
age
}
# OR 逻辑
youngOrOld(func: has(age)) @filter(lt(age, 18) OR gt(age, 65)) {
name
age
}
# NOT 逻辑
noEmail(func: has(name)) @filter(NOT has(email)) {
name
}
}
比较运算符
{
# 数值比较
users(func: has(age)) @filter(age = 25) {
name
age
}
# 范围查询
adults(func: has(age)) @filter(age > 18 AND age < 65) {
name
age
}
}
控制逻辑
DQL提供多种控制逻辑来精确控制查询行为:
条件过滤
{
# 基本过滤
users(func: has(name)) @filter(eq(name, "Alice")) {
name
age
}
# 复杂过滤
adults(func: has(age)) @filter(ge(age, 18) AND has(email)) {
name
age
email
}
}
结果控制
{
# 结果裁剪 - 只返回有完整数据的节点
users(func: has(name)) @cascade {
name
age
friend {
name
}
}
# 结果扁平化 - 将嵌套结构扁平化
users(func: has(name)) @normalize {
name
friend {
name
}
}
# 分页控制
users(func: has(name), first: 10, offset: 20) {
name
age
}
# 排序
users(func: has(age), orderasc: age) {
name
age
}
}
语法拆解
通过具体示例深入理解DQL查询的语法结构:
示例查询
network(func: eq(name, "Alice")) @recurse(depth: 3) {
name
friend {
name
}
}
语法拆解
| 组成部分 | 说明 | 示例 |
|---|---|---|
| 1. network | 查询块别名 (alias) | 给查询结果起名字,返回JSON时包在 "network": [...] 下 |
| 2. func: | 关键字 (keyword) | 表示「入口函数」,只能写 func:,不能换成别的 |
| 3. eq(name, "Alice") | 入口函数 (function) | 选出所有 name 等于 "Alice" 的节点作为查询起点 |
| 4. @recurse(depth: 3) | 查询修饰符 (directive) | 递归查询,自动沿着边展开,depth: 3 限制最多走3步关系 |
| 5. { ... } | 结果字段选择 (projection) | 定义要返回哪些属性/关系 |
| 6. name | 属性字段 | 返回每个节点的 name 属性,
这里的 name 是标识符,完整的写法是<name>,
使用中文时, < >不能省略!!! |
| 7. friend { name } | 关系字段 (edge) | 从当前节点沿着 friend 边走到相关节点,返回它们的 name |
执行逻辑总结
执行步骤
- 起点:找到所有
name = "Alice"的节点 - 递归:从这些节点出发,顺着
friend关系往外扩展,最多3层 - 返回:每一层节点的
name和它的friend.name - 输出格式:包在JSON里的
"network": [...]下
结果说明
network 查询得到的就是「Alice 的社交网络」,递归展开到3层朋友。
谓语类型
理解 Dgraph 中的谓词系统、类型定义和约束
什么是谓词?
谓词是描述对象信息的最小单元,可以是文字值,也可以是与其他实体的关系。
核心理解
- 谓词是三元组中的"谓词"部分:
<主语> <谓词> <宾语> - 每个谓词都有特定的数据类型和约束
- 谓词可以是标量值(字符串、数字等)或关系(指向其他节点)
谓词声明模式
Dgraph 集群的模式决定是否必须先定义谓词才能执行数据变更:
Strict 模式
您必须在模式中声明谓词后,才可以通过 mutation 插入数据。
# 启动 Alpha 节点时设置 --limit 参数
dgraph alpha --limit "mutations=strict; mutations-nquad=1000000" --my=<alpha-node-ip>:7080 --zero=<zero-node-ip>:5080
这会启用严格模式,只允许对已在 schema 中的谓词进行突变操作。在执行突变之前,需要先通过 alter 操作声明谓词及其 schema 类型。
Flexible 模式(默认)
可以在 mutation 中使用未声明的谓词,Dgraph 会自动推断并添加这些谓词到模式里。
📌 注意:当通过 GraphQL API 部署模式时,Dgraph 会自动生成底层的 Dgraph 类型。
谓词类型分类
谓词类型用于指示谓词所能存储的数据类型、是否为列表、是否需要索引以及是否支持多语言等:
1. 标量类型(Scalar types)
| 类型名称 | 对应 Go 类型 | 说明 |
|---|---|---|
string / default |
string |
默认字符串类型 |
int |
int64 |
整数类型 |
float |
float |
浮点类型 |
bool |
bool |
布尔型 |
dateTime |
time.Time |
日期时间,要符合 RFC 3339 格式 |
geo |
geo 类型 |
地理位置类型(支持 go-geom) |
password |
string(加密存储) |
加密后的密码,用于安全验证 |
float32vector |
[]float32 |
浮点数数组,常用于存储 embeddings |
2. UID 类型
用于表示关系,在内部每个节点通过 uint64 类型的 UID 唯一标识。
# 关系谓词示例
friends: [uid] .
parent: uid .
children: [uid] @reverse .
多语言支持(Predicates i18n)
支持通过 IRI 格式的谓词名称(使用 <> 符号括起)和语言标签:
# Schema 定义
<公司>: string @index(fulltext) @lang .
# Mutation 示例
{
set {
_:a <公司> "Dgraph Labs Inc"@en .
_:b <公司> "夏新科技有限责任公司"@zh .
_:a <dgraph.type> "Company" .
}
}
📌 关键点:若需针对不同语言进行全文索引,应使用 @lang 指令,并在 mutation 时使用语言标签。
唯一性约束(@unique)
通过 @unique 指令可以确保该谓词的值在所有节点中唯一:
# 字符串类型需要 hash 或 exact 索引
email: string @unique @index(exact) .
# 整数类型需要 int 索引
user_id: int @unique @index(int) .
重要规则
- 字符串类型:需要
hash或exact索引 - 整数类型:需要
int索引 - 必须同时定义索引才能使用
@unique
Upsert 指令(@upsert)
用于执行"先查再插"操作,当两个事务尝试创建同一数据时,可确保不会冲突:
email: string @index(exact) @upsert .
该做法会检查索引键,并防止写入冲突。
防冲突指令(@noconflict)
这是一个试验性指令,可用于避免在某些情况下检测冲突:
email: string @index(exact) @noconflict .
⚠️ 警告:但有可能导致数据丢失,不推荐在高正确性场景使用。
密码类型(password)
密码属性使用 password 类型定义,密码被加密保存(bcrypt),不可直接查询:
Schema 定义
pass: password .
Mutation 设置密码
{
set {
<0x123> <name> "Password Example" .
<0x123> <pass> "ThePassword" .
}
}
验证密码
{
check(func: uid(0x123)) {
name
checkpwd(pass, "ThePassword")
}
}
返回格式示例:
{
"data": {
"check": [
{
"name": "Password Example",
"checkpwd(pass)": true
}
]
}
}
使用别名形式
{
check(func: uid(0x123)) {
name
secret: checkpwd(pass, "ThePassword")
}
}
向量类型(float32vector)
float32vector 表示浮点数数组,常用于存储机器学习模型生成的 embeddings:
# Schema 定义
embedding: float32vector @index(hnsw) .
# 在建立 hnsw 索引后,可以结合 similar_to 函数进行相似度搜索
{
similar(func: similar_to(embedding, [0.1, 0.2, 0.3, ...])) {
uid
name
}
}
谓词命名规范
| 规则类型 | 说明 |
|---|---|
| 基本规则 | 可使用字母数字组合,也支持国际化资源标识符(IRI)格式 |
| 保留命名空间 | 无法定义以 dgraph. 开头的类型或谓词 |
| 支持的特殊字符 | ][&*()_-+=!#$%(只要前后有字母或数字) |
| 不支持的特殊字符 | ^}|{~` |
基于 RDF 类型的谓词类型推断
使用 RDF 类型进行 mutation 时,即使模式中已有定义,类型可能会被 RDF 类型覆盖:
重要说明
- 如果类型不一致且不能转换,mutation 会报错
- 如果
age未定义,第一次 mutation 为xs:int类型,则模式设置为int - 后续类型兼容则转换,若不兼容则报错
核心要点总结
- 谓词是描述对象信息的最小单元,可以是文字值或关系
- 两种模式:strict 模式需要预先声明,flexible 模式自动推断
- 标量类型:string、int、float、bool、dateTime、geo、password、float32vector
- UID 类型:用于表示实体间的关系
- 多语言支持:使用
@lang指令和语言标签 - 约束指令:
@unique、@upsert、@noconflict - 密码类型:使用
checkpwd函数验证,不能直接查询
谓语指令
掌握 Dgraph 中谓词级别的各种指令和配置
什么是谓语指令?
谓词是 Dgraph 的核心(相当于边/属性)。所有指令几乎都是定义在谓词上的。
核心理解
- 谓词级别的指令用于配置谓词的行为和特性
- 这些指令决定了如何存储、索引和查询数据
- 不同的指令组合可以实现复杂的数据操作需求
@index 索引指令
给谓词建索引,支持不同类型的索引方式,是查询性能的关键:
字符串类型索引
# 不同字符串索引类型
name: string @index(term) . # 词项索引,支持部分匹配
email: string @index(exact) . # 精确匹配索引
description: string @index(trigram) . # 三元组索引,支持模糊搜索
content: string @index(fulltext) . # 全文索引,支持语言分析
pattern: string @index(regexp) . # 正则表达式索引
| 索引类型 | 用途 | 查询函数 |
|---|---|---|
term |
词项匹配,支持部分匹配 | allofterms, anyofterms |
exact |
精确匹配 | eq, in |
trigram |
模糊搜索,支持拼写错误 | match |
fulltext |
全文搜索,支持语言分析 | alloftext, anyoftext |
regexp |
正则表达式匹配 | regexp |
数值和日期类型索引
# 数值类型索引
age: int @index(int) .
score: float @index(float) .
# 日期时间索引
created_at: dateTime @index(year) . # 按年索引
updated_at: dateTime @index(day) . # 按天索引
event_time: dateTime @index(month) . # 按月索引
log_time: dateTime @index(hour) . # 按小时索引
特殊类型索引
# 地理位置索引
location: geo @index(geo) .
# 向量索引(用于机器学习)
embedding: float32vector @index(hnsw(metric: "cosine")) .
similarity: float32vector @index(hnsw(metric: "euclidean")) .
@reverse 反向指令
为 UID 边建立反向谓词,可以用 <~edge> 查询:
# Schema 定义
parent: [uid] @reverse .
children: [uid] @reverse .
# 查询示例
{
# 查询某个人的所有孩子
person(func: uid(0x123)) {
name
children {
name
}
}
# 查询某个人的所有父母(使用反向关系)
child(func: uid(0x456)) {
name
<~parent> {
name
}
}
}
📌 关键点:反向关系让您可以双向遍历图结构,无需显式存储两个方向的边。
@count 计数指令
为 UID 边建立 count 索引,可以快速获取边的数量:
# Schema 定义
friends: [uid] @count .
posts: [uid] @count .
# 查询示例
{
users(func: gt(count(friends), 10)) {
name
count(friends)
}
# 按朋友数量排序
popular_users(func: type(User), orderdesc: count(friends)) {
name
count(friends)
}
}
@upsert 更新插入指令
用于 upsert(先查再写)操作,保证唯一性时避免冲突:
# Schema 定义
email: string @index(exact) @upsert .
username: string @index(exact) @upsert .
# Mutation 示例
{
set {
_:user <email> "alice@example.com" .
_:user <name> "Alice" .
_:user <dgraph.type> "User" .
}
}
📌 工作原理:如果已存在相同 email 的用户,则更新该用户;否则创建新用户。
@unique 唯一性指令
确保某个谓词在所有节点中唯一(需要配合索引):
# Schema 定义
email: string @unique @index(exact) .
user_id: int @unique @index(int) .
phone: string @unique @index(hash) .
重要规则
- 字符串类型:需要
hash或exact索引 - 整数类型:需要
int索引 - 尝试插入重复值会导致 mutation 失败
@noconflict 防冲突指令
实验性指令,禁用事务冲突检测:
# Schema 定义
counter: int @noconflict .
status: string @noconflict .
⚠️ 警告:这可能导致数据丢失,不推荐在高正确性场景使用。
@lang 多语言指令
启用多语言支持,可以在字符串值后添加 @en、@zh 等:
# Schema 定义
title: string @index(fulltext) @lang .
description: string @index(fulltext) @lang .
# Mutation 示例
{
set {
_:article <title> "Hello World"@en .
_:article <title> "你好世界"@zh .
_:article <description> "A greeting"@en .
_:article <description> "一个问候"@zh .
_:article <dgraph.type> "Article" .
}
}
# 查询示例
{
articles(func: alloftext(title@en, "Hello")) {
title@en
title@zh
}
}
查询指令(非 Schema 指令)
严格说,这些是查询指令,不是 schema 指令,但很多人会混淆:
@cascade 级联指令
{
users(func: type(User)) @cascade {
name
posts {
title
comments {
content
}
}
}
}
只返回所有嵌套字段都有值的用户。
@normalize 标准化指令
{
users(func: type(User)) @normalize {
name
posts {
title
}
}
}
将嵌套结构扁平化,每个 post 都会产生一个独立的用户记录。
指令组合使用
多个指令可以组合使用,实现复杂的数据需求:
# 复杂的谓词定义示例
email: string @index(exact) @unique @upsert .
name: string @index(term) @lang .
friends: [uid] @count @reverse .
location: geo @index(geo) .
embedding: float32vector @index(hnsw(metric: "cosine")) .
created_at: dateTime @index(year) .
tags: [string] @index(term) .
最佳实践
- 根据查询需求选择合适的索引类型
- 唯一性约束需要配合相应的索引
- 多语言支持需要配合全文索引
- 向量索引用于机器学习和相似度搜索
核心要点总结
- @index:各种索引类型,决定查询性能和方式
- @reverse:建立反向关系,支持双向遍历
- @count:快速获取边的数量
- @upsert:先查再写,避免冲突
- @unique:确保唯一性,需要配合索引
- @noconflict:实验性,禁用冲突检测
- @lang:多语言支持
- @cascade/@normalize:查询指令,非 schema 指令
节点类型
理解和使用 dgraph.type 标签系统
什么是 dgraph.type?
dgraph.type 是 Dgraph 内置的系统谓词。
它的作用是:给某个节点打上一个或多个 类型标签(type/tag)。
在 GraphQL schema 中定义的类型(type User { ... })最终也会映射为节点上的 dgraph.type 属性。
核心理解
- Dgraph 底层没有真正的"节点类型",所有节点本质上都是一堆三元组
- 但通过
dgraph.type,可以人为地为节点分组,使其具有"类型"的语义
基本语法
给节点添加类型标签的 mutation 写法:
RDF 语法
mutation {
set {
_:u1 <name> "Alice" .
_:u1 <age> "25" .
_:u1 <dgraph.type> "User" .
}
}
这里:
_:u1是新建节点的临时 blank node ID<dgraph.type> "User"表示该节点类型为 User
JSON 语法
mutation {
set {
"uid": "_:u1",
"name": "Alice",
"age": 25,
"dgraph.type": "User"
}
}
多类型标签
一个节点可以有多个类型:
mutation {
set {
_:m1 <name> "Inception" .
_:m1 <release_date> "2010-07-16" .
_:m1 <dgraph.type> "Film" .
_:m1 <dgraph.type> "SciFi" .
}
}
📌 节点 m1 同时属于 Film 和 SciFi 类型。
查询时使用 dgraph.type
你可以用 type() 函数筛选节点:
{
q(func: type(User)) {
uid
name
age
}
}
这会返回所有 dgraph.type 包含 "User" 的节点。
结合 Schema 类型定义
节点类型是可选定义,用于声明某种类型节点应包含哪些谓词:
# 首先在 Schema 中声明谓词
name: string @index(term) .
dob: datetime .
home_address: string .
friends: [uid] .
# 然后定义类型
type Student {
name
dob
home_address
friends
}
重要规则
- 类型定义中的所有谓词必须已在类型模式中声明
- 不同节点类型可以共用相同谓词
- 即使使用了类型,也可以为节点添加未声明的额外谓词
反向谓词(Reverse predicates)
使用 @reverse 可定义反向关系,并在类型中加以展示:
# Schema 定义
children: [uid] @reverse .
name: string @index(term) .
# 类型定义
type Parent {
name
children
}
type Child {
name
<~children>
}
这里 <~children> 表示反向关系,即从子节点指向父节点。
主要使用场景
节点类型主要用于以下两类操作:
1. 删除操作
delete {
<0x123> * * .
}
使用 delete { <uid> * * . } 删除节点所有信息时,Dgraph 可根据类型定义识别哪些谓词需要删除。
2. 展开操作
{
q(func: uid(0x123)) {
expand(all)
}
}
使用 expand(all) 查询所有谓词时,Dgraph 可根据类型定义识别哪些谓词需要展开。
⚠️ 注意:即使使用了类型,也可以为节点添加未声明的额外谓词,操作如 expand(all) 或删除可能不会影响这些额外谓词。
完整示例:电影数据库
以下是基于电影与演员数据库构建的完整模式示例:
# 谓词定义
director.film: [uid] @reverse .
actor.film: [uid] @count .
genre: [uid] @reverse .
initial_release_date: dateTime @index(year) .
name: string @index(exact, term) @lang .
starring: [uid] .
performance.film: [uid] .
performance.character_note: string .
performance.character: [uid] .
performance.actor: [uid] .
performance.special_performance_type: [uid] .
type: [uid] .
# 类型定义
type Person {
name
director.film
actor.film
}
type Movie {
name
initial_release_date
genre
starring
}
type Genre {
name
}
type Performance {
performance.film
performance.character
performance.actor
}
特殊说明
| 规则 | 说明 |
|---|---|
| 数据类型 | dgraph.type 必须是字符串(string),不能是 uid |
| 大小写敏感 | 值区分大小写,例如 "User" 与 "user" 是不同的类型 |
| 多类型支持 | 节点可以拥有多个类型(值为字符串数组),如 ["Pet", "Animal"] |
| 类型定义规则 | 类型定义中的所有谓词必须已在类型模式中声明 |
| 额外谓词 | 即使使用了类型,也可以为节点添加未声明的额外谓词 |
| GraphQL 集成 | 在 GraphQL API 中写 mutation { addUser(...) } 时,底层其实就是自动在节点上打了
dgraph.type: "User"
|
核心要点总结
- dgraph.type 是 Dgraph 内置的标签系统,用来给节点分组和定义类型
- 节点类型是可选定义,用于声明某种类型节点应包含哪些谓词
- 主要用途:删除操作和
expand(all)查询时识别相关谓词 - 支持多类型:一个节点可以拥有多个类型标签
- 反向关系:使用
@reverse和<~predicate>语法 - 在 DQL 里手动设置,在 GraphQL 里由系统自动生成
增删改查
DQL查询模式和Mutation数据变更完整指南
查询模式
DQL提供多种查询模式来满足不同的数据检索需求:
基本查询
query {
user(func: eq(name, "Alice")) {
uid
name
age
}
}
按类型查询
{
# 使用 type() 函数
users(func: type(User)) {
uid
name
age
}
# 使用 @filter 过滤
users(func: has(name)) @filter(eq(dgraph.type, "User")) {
uid
name
age
}
}
递归查询
{
# 无限层级递归
network(func: eq(name, "Alice")) @recurse {
name
friend {
name
}
}
# 限制递归深度
network(func: eq(name, "Alice")) @recurse(depth: 3) {
name
friend {
name
}
}
}
多块查询
{
# 用户查询
users(func: type(User)) {
uid
name
age
}
# 电影查询
movies(func: type(Movie)) {
uid
title
year
}
# 关系查询
relationships(func: has(friend)) {
uid
friend {
name
}
}
}
参数化查询
query all($name: string, $minAge: int) {
users(func: eq(name, $name)) @filter(ge(age, $minAge)) {
uid
name
age
}
}
请求变量:
{
"name": "Alice",
"minAge": 18
}
聚合查询
{
stats(func: has(age)) {
count(uid) # 总数量
sum(age) # 年龄总和
avg(age) # 平均年龄
min(age) # 最小年龄
max(age) # 最大年龄
}
}
分组查询
{
# 按年龄分组统计
ageGroups(func: has(age)) @groupby(age) {
count(uid)
}
# 按类型分组统计
typeGroups(func: has(dgraph.type)) @groupby(dgraph.type) {
count(uid)
}
}
边属性(Facet)查询
{
users(func: has(name)) {
name
friend @facets(since, closeness) { # 查询边的属性
name
}
}
}
展开查询
{
# 展开所有字段
users(func: eq(name, "Alice")) {
expand(_all_) {
expand(_all_)
}
}
# 展开特定类型的所有字段
users(func: type(User)) {
expand(User)
}
}
Mutation(数据变更)
DQL的Mutation操作支持多种数据变更模式:
新增节点
使用RDF格式创建新节点:
mutation {
set {
_:alice <name> "Alice Johnson" .
_:alice <age> "30" .
_:alice <email> "alice@example.com" .
_:alice <dgraph.type> "User" .
}
}
使用JSON格式创建新节点:
mutation {
set {
"uid": "_:alice",
"dgraph.type": "User",
"name": "Alice Johnson",
"age": 30,
"email": "alice@example.com"
}
}
创建关系
mutation {
set {
_:alice <name> "Alice" .
_:alice <dgraph.type> "User" .
_:bob <name> "Bob" .
_:bob <dgraph.type> "User" .
_:alice <friend> _:bob .
_:bob <friend> _:alice . # 双向关系
}
}
更新节点
mutation {
set {
<0x1> <age> "31" .
<0x1> <email> "alice.new@example.com" .
<0x1> <lastLogin> "2024-01-15T10:30:00Z" .
}
}
更新类型标签
mutation {
set {
<0x1> <dgraph.type> "Employee" . # 添加新类型
<0x1> <dgraph.type> "Manager" . # 添加多个类型
}
}
删除操作
mutation {
delete {
<0x1> <email> * . # 删除email属性
<0x1> <friend> <0x2> . # 删除特定关系
<0x1> <dgraph.type> "Manager" . # 删除特定类型标签
}
}
mutation {
delete {
<0x1> * * . # 删除整个节点及其所有属性和关系
}
}
事务控制
# 立即提交事务
mutation {
set {
_:alice <name> "Alice" .
_:alice <dgraph.type> "User" .
}
commitNow: true
}
# 指定事务开始时间戳
mutation {
set {
_:alice <name> "Alice" .
}
startTs: 1234567890
}
# 回滚事务
mutation {
set {
_:alice <name> "Alice" .
}
abort: true
}
批量操作
mutation {
set {
_:person1 <name> "Alice" .
_:person1 <age> "30" .
_:person1 <dgraph.type> "User" .
_:person2 <name> "Bob" .
_:person2 <age> "28" .
_:person2 <dgraph.type> "User" .
_:person3 <name> "Charlie" .
_:person3 <age> "32" .
_:person3 <dgraph.type> "User" .
# 建立关系网络
_:person1 <friend> _:person2 .
_:person2 <friend> _:person3 .
_:person1 <friend> _:person3 .
}
}
条件更新
{
# 先查询需要更新的节点
var(func: eq(name, "Alice")) {
alice as uid
}
# 然后更新
mutation {
set {
uid(alice) <status> "active" .
uid(alice) <lastLogin> "2024-01-15T10:30:00Z" .
}
}
}
类型标签操作
管理节点的类型标签系统:
添加类型标签
mutation {
set {
<0x1> <dgraph.type> "Employee" . # 给现有节点添加Employee类型
<0x1> <dgraph.type> "Manager" . # 同时添加Manager类型
<0x1> <dgraph.type> "Admin" . # 可以添加多个类型
}
}
删除类型标签
mutation {
delete {
<0x1> <dgraph.type> "Manager" . # 删除Manager类型标签
}
}
按类型查询
{
# 查询所有Employee
employees(func: type(Employee)) {
uid
name
dgraph.type
}
# 查询既是Person又是Employee的节点
personEmployees(func: type(Person, Employee)) {
uid
name
dgraph.type
}
# 查询包含特定类型的所有节点
allUsers(func: has(dgraph.type)) @filter(uid_in(dgraph.type, "User", "Employee")) {
uid
name
dgraph.type
}
}
类型统计
{
# 按类型分组统计
typeStats(func: has(dgraph.type)) @groupby(dgraph.type) {
count(uid)
}
# 统计特定类型的数量
userCount(func: type(User)) {
count(uid)
}
}
高级操作
复杂的数据操作和查询模式:
Upsert操作
{
# 查询或创建
var(func: eq(email, "alice@example.com")) {
alice as uid
}
mutation {
set {
uid(alice) <name> "Alice" .
uid(alice) <email> "alice@example.com" .
uid(alice) <dgraph.type> "User" .
}
}
}
复杂关系操作
{
# 查询朋友的朋友
var(func: eq(name, "Alice")) {
friends as friend
}
friendsOfFriends(func: uid(friends)) {
name
friend {
name
}
}
}
数据迁移
{
# 查询需要迁移的数据
var(func: type(OldUser)) {
oldUsers as uid
}
# 迁移数据
mutation {
set {
uid(oldUsers) <dgraph.type> "User" .
}
delete {
uid(oldUsers) <dgraph.type> "OldUser" .
}
}
}
中文支持
Dgraph 对中文编码的完整支持和最佳实践
Dgraph 对中文的支持
Dgraph 默认支持 UTF-8 编码,这意味着对中文编码有完整的原生支持。
核心要点
- 节点(主语):完全支持中文标识符
- 边(谓语):完全支持中文谓词名
- 属性值:完全支持中文字符串
- 唯一限制:使用中文标识符时,不能省略
< >尖括号
重要规则:尖括号不能省略
当使用中文作为节点或谓词标识符时,必须使用尖括号:
❌ 错误写法
# 错误:中文标识符没有尖括号
张三 <姓名> "张三" .
张三 <年龄> "25" .
张三 <朋友> 李四 .
✅ 正确写法
# 正确:中文标识符使用尖括号
<张三> <姓名> "张三" .
<张三> <年龄> "25" .
<张三> <朋友> <李四> .
完整的中文示例
以下是一个完整的中文数据模型示例:
Schema 定义
# 中文谓词定义
<姓名>: string @index(term) .
<年龄>: int @index(int) .
<职业>: string @index(term) .
<公司>: string @index(term) .
<朋友>: [uid] @reverse .
<同事>: [uid] @reverse .
<居住地>: string @index(term) .
# 中文类型定义
type 人员 {
<姓名>
<年龄>
<职业>
<公司>
<朋友>
<同事>
<居住地>
}
数据插入
mutation {
set {
<张三> <姓名> "张三" .
<张三> <年龄> 28 .
<张三> <职业> "软件工程师" .
<张三> <公司> "阿里巴巴" .
<张三> <居住地> "杭州" .
<张三> <dgraph.type> "人员" .
<李四> <姓名> "李四" .
<李四> <年龄> 26 .
<李四> <职业> "产品经理" .
<李四> <公司> "腾讯" .
<李四> <居住地> "深圳" .
<李四> <dgraph.type> "人员" .
<王五> <姓名> "王五" .
<王五> <年龄> 30 .
<王五> <职业> "设计师" .
<王五> <公司> "字节跳动" .
<王五> <居住地> "北京" .
<王五> <dgraph.type> "人员" .
# 建立关系
<张三> <朋友> <李四> .
<张三> <朋友> <王五> .
<李四> <同事> <王五> .
}
}
数据查询
{
# 查询所有人员
所有人员(func: type(人员)) {
<姓名>
<年龄>
<职业>
<公司>
<居住地>
}
# 查询张三的朋友
张三的朋友(func: eq(<姓名>, "张三")) {
<姓名>
<朋友> {
<姓名>
<职业>
}
}
# 查询在杭州的人员
杭州人员(func: eq(<居住地>, "杭州")) {
<姓名>
<职业>
<公司>
}
}
多语言混合使用
Dgraph 支持中英文混合使用,提供了极大的灵活性:
# 中英文混合的 Schema
name: string @index(term) .
<姓名>: string @index(term) .
age: int @index(int) .
<年龄>: int @index(int) .
company: string @index(term) .
<公司>: string @index(term) .
# 中英文混合的数据
{
set {
<user1> name "Alice" .
<user1> <姓名> "爱丽丝" .
<user1> age 25 .
<user1> <年龄> 25 .
<user1> company "Google" .
<user1> <公司> "谷歌" .
}
}
中文索引和查询
中文文本支持各种索引类型和查询方式:
全文索引
# Schema 定义
<文章内容>: string @index(fulltext) @lang .
# 数据插入
{
set {
<article1> <文章内容> "人工智能正在改变世界"@zh .
<article1> <文章内容> "Artificial Intelligence is changing the world"@en .
}
}
# 中文全文搜索
{
搜索结果(func: alloftext(<文章内容>@zh, "人工智能")) {
<文章内容>@zh
}
}
词项索引
# Schema 定义
<标签>: [string] @index(term) .
# 数据插入
{
set {
<product1> <标签> "智能手机" .
<product1> <标签> "5G" .
<product1> <标签> "拍照" .
}
}
# 词项搜索
{
产品搜索(func: allofterms(<标签>, "智能手机 拍照")) {
<标签>
}
}
最佳实践
| 场景 | 建议 | 示例 |
|---|---|---|
| 标识符命名 | 使用有意义的中文名称 | <用户>, <订单>, <产品> |
| 谓词命名 | 保持简洁明了 | <姓名>, <年龄>, <创建时间> |
| 类型定义 | 使用业务领域术语 | type 用户, type 订单 |
| 索引选择 | 根据查询需求选择 | 精确匹配用 exact,模糊搜索用 term |
| 多语言支持 | 使用 @lang 指令 |
<标题>: string @index(fulltext) @lang |
常见问题和解决方案
问题1:中文查询结果为空
原因:可能没有正确使用尖括号或索引配置不当
解决:确保中文标识符使用 <> 包围,并配置合适的索引
问题2:中文字符显示乱码
原因:客户端编码设置问题
解决:确保客户端使用 UTF-8 编码
问题3:中文全文搜索不准确
原因:没有使用 @lang 指令
解决:添加 @lang 指令并指定语言标签
核心要点总结
- UTF-8 原生支持:Dgraph 默认支持中文编码
- 尖括号必须:中文标识符必须使用
<>包围 - 完整功能支持:节点、边、属性值都支持中文
- 索引支持:中文文本支持各种索引类型
- 多语言混合:可以中英文混合使用
- 全文搜索:使用
@lang指令支持中文全文搜索 - 最佳实践:使用有意义的命名和合适的索引