跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

客户端/SDK

HugeGraph 官方多语言客户端 SDK(Java、Python、Go 等)概览与接入指引。

HugeGraph 提供多语言客户端 SDK,方便在不同语言与技术栈中连接 HugeGraph Server,进行 Schema 管理、顶点与边数据读写、Gremlin 遍历及高级分析。

支持的客户端

  • HugeGraph Java Client

    官方核心 Java SDK,提供与 Gremlin 语法相近的 API 风格,支持完整的 Schema 管理、CRUD、Gremlin 查询及 Traverser 算法,并支持 GraphSpace 隔离。

  • HugeGraph Python Client

    官方 Python SDK(pyhugegraph),位于 HugeGraph-AI 仓库,支持管理 Schema、读写图数据及提交 Gremlin 查询,深度集成 HugeGraph-LLM 与 HugeGraph-ML。

  • HugeGraph Go Client

    官方 Go SDK,支持版本查询、Schema 定义(PropertyKey/VertexLabel/EdgeLabel)、顶点操作与 Gremlin 查询。

选择建议

  • 生产级 Java/Scala 服务:推荐使用 HugeGraph Java Client,功能最完备,覆盖所有底层能力与连接池管理。
  • AI/LLM/算法与数据科学应用:推荐使用 HugeGraph Python Client(pyhugegraph),深度适配 HugeGraph-LLM、HugeGraph-ML 及 Python 数据科学分析工作流。
  • 微服务与云原生工具构建:推荐使用 HugeGraph Go Client 或直接调用 RESTful API。
  • 终端离线调试或临时查询:推荐使用 Gremlin Console。

1 - HugeGraph Java Client

1 HugeGraph-Client 概述

HugeGraph Java Client 将 Java API 转换为 HugeGraph Server 的 REST 请求,支持管理 Schema 和图数据、执行 Gremlin 及调用 Traverser API。本文涵盖 Java 项目的快速接入示例与全量核心 API 参考。

其他语言可使用 Go Client 或 Python Client。

2 环境要求

  • JDK 17,用于本文示例及从 Toolchain master 构建 Client 1.8.0
  • Maven 3.6.3+

3 使用流程

按下面的顺序接入 HugeGraph-Client。

  1. 使用 IntelliJ IDEA 或 Eclipse 新建 Maven 工程。
  2. 在 pom.xml 中添加 HugeGraph-Client 依赖。
  3. 创建客户端、调用 API,并在使用后关闭客户端。

详细操作见下面的完整示例。

4 完整示例

4.1 新建 Maven 工程

使用 Eclipse 或 IntelliJ IDEA 创建 Maven 工程。

4.2 添加 hugegraph-client 依赖

在 pom.xml 中添加依赖。

1
2<dependencies>
3    <dependency>
4        <groupId>org.apache.hugegraph</groupId>
5        <artifactId>hugegraph-client</artifactId>
6        <!-- 以下完整示例可使用已发布的 1.7.0 -->
7        <version>1.7.0</version>
8    </dependency>
9</dependencies>

先根据用途选择客户端版本。

用途客户端版本Java 编译目标
运行下方完整示例已发布的 1.7.0,使用上面的依赖即可发布版 POM 为 Java 8;本文统一使用 JDK 17
使用能力探测等 master 新接口Toolchain master(以 1.8 为基线)Java 17

示例使用的 Schema、Graph、Gremlin 和资源关闭接口在 Client 1.7.0 中可用,也与 Toolchain master 兼容。 发布版的 Java 编译目标不代表所有传递依赖的运行环境要求。

若需要使用 master 分支未发布的新接口,可从源码编译安装 Client(需配合 Toolchain 源码,详见 Tools 源码构建指引):

1java -version
2mvn -version
3mvn -Dmaven.repo.local="${candidate_dir:?Run the candidate SDK setup first}/m2" \
4  -Dsdk.validation.mode=candidate \
5  install -pl hugegraph-client -am -DskipTests -Dmaven.javadoc.skip=true -ntp

两条版本检查都应显示 JDK 17。使用 master 分支 Client 的项目运行 Maven 命令时,也需添加 -Dmaven.repo.local="$candidate_dir/m2"。 Client 与 Server 的版本不必相同;升级前核对所需 API 及兼容范围。

4.3 Example

选择单条操作或批量操作示例,将完整代码保存为 Maven 工程中的 src/main/java/SingleExample.java 或 src/main/java/BatchExample.java。复制按钮会包含已折叠的代码行。

4.3.1 SingleExample
  1import java.io.IOException;
  2import java.util.Iterator;
  3import java.util.List;
  4
  5import org.apache.hugegraph.driver.GraphManager;
  6import org.apache.hugegraph.driver.GremlinManager;
  7import org.apache.hugegraph.driver.HugeClient;
  8import org.apache.hugegraph.driver.SchemaManager;
  9import org.apache.hugegraph.structure.constant.T;
 10import org.apache.hugegraph.structure.graph.Edge;
 11import org.apache.hugegraph.structure.graph.Path;
 12import org.apache.hugegraph.structure.graph.Vertex;
 13import org.apache.hugegraph.structure.gremlin.Result;
 14import org.apache.hugegraph.structure.gremlin.ResultSet;
 15
 16public class SingleExample {
 17
 18    public static void main(String[] args) throws IOException {
 19        // If connect failed will throw a exception.
 20        HugeClient hugeClient = HugeClient.builder("http://localhost:8080",
 21                                                   "DEFAULT",
 22                                                   "hugegraph")
 23                                          .configUser("username", "password")
 24                                          // 这是示例,生产环境需要使用安全的凭证
 25                                          .build();
 26
 27        SchemaManager schema = hugeClient.schema();
 28
 29        schema.propertyKey("name").asText().ifNotExist().create();
 30        schema.propertyKey("age").asInt().ifNotExist().create();
 31        schema.propertyKey("city").asText().ifNotExist().create();
 32        schema.propertyKey("weight").asDouble().ifNotExist().create();
 33        schema.propertyKey("lang").asText().ifNotExist().create();
 34        schema.propertyKey("date").asDate().ifNotExist().create();
 35        schema.propertyKey("price").asInt().ifNotExist().create();
 36
 37        schema.vertexLabel("person")
 38              .properties("name", "age", "city")
 39              .primaryKeys("name")
 40              .ifNotExist()
 41              .create();
 42
 43        schema.vertexLabel("software")
 44              .properties("name", "lang", "price")
 45              .primaryKeys("name")
 46              .ifNotExist()
 47              .create();
 48
 49        schema.indexLabel("personByCity")
 50              .onV("person")
 51              .by("city")
 52              .secondary()
 53              .ifNotExist()
 54              .create();
 55
 56        schema.indexLabel("personByAgeAndCity")
 57              .onV("person")
 58              .by("age", "city")
 59              .secondary()
 60              .ifNotExist()
 61              .create();
 62
 63        schema.indexLabel("softwareByPrice")
 64              .onV("software")
 65              .by("price")
 66              .range()
 67              .ifNotExist()
 68              .create();
 69
 70        schema.edgeLabel("knows")
 71              .sourceLabel("person")
 72              .targetLabel("person")
 73              .properties("date", "weight")
 74              .ifNotExist()
 75              .create();
 76
 77        schema.edgeLabel("created")
 78              .sourceLabel("person").targetLabel("software")
 79              .properties("date", "weight")
 80              .ifNotExist()
 81              .create();
 82
 83        schema.indexLabel("createdByDate")
 84              .onE("created")
 85              .by("date")
 86              .secondary()
 87              .ifNotExist()
 88              .create();
 89
 90        schema.indexLabel("createdByWeight")
 91              .onE("created")
 92              .by("weight")
 93              .range()
 94              .ifNotExist()
 95              .create();
 96
 97        schema.indexLabel("knowsByWeight")
 98              .onE("knows")
 99              .by("weight")
100              .range()
101              .ifNotExist()
102              .create();
103
104        GraphManager graph = hugeClient.graph();
105        Vertex marko = graph.addVertex(T.LABEL, "person", "name", "marko",
106                                       "age", 29, "city", "Beijing");
107        Vertex vadas = graph.addVertex(T.LABEL, "person", "name", "vadas",
108                                       "age", 27, "city", "Hongkong");
109        Vertex lop = graph.addVertex(T.LABEL, "software", "name", "lop",
110                                     "lang", "java", "price", 328);
111        Vertex josh = graph.addVertex(T.LABEL, "person", "name", "josh",
112                                      "age", 32, "city", "Beijing");
113        Vertex ripple = graph.addVertex(T.LABEL, "software", "name", "ripple",
114                                        "lang", "java", "price", 199);
115        Vertex peter = graph.addVertex(T.LABEL, "person", "name", "peter",
116                                       "age", 35, "city", "Shanghai");
117
118        marko.addEdge("knows", vadas, "date", "2016-01-10", "weight", 0.5);
119        marko.addEdge("knows", josh, "date", "2013-02-20", "weight", 1.0);
120        marko.addEdge("created", lop, "date", "2017-12-10", "weight", 0.4);
121        josh.addEdge("created", lop, "date", "2009-11-11", "weight", 0.4);
122        josh.addEdge("created", ripple, "date", "2017-12-10", "weight", 1.0);
123        peter.addEdge("created", lop, "date", "2017-03-24", "weight", 0.2);
124
125        GremlinManager gremlin = hugeClient.gremlin();
126        System.out.println("==== Path ====");
127        ResultSet resultSet = gremlin.gremlin("g.V().outE().path()").execute();
128        Iterator<Result> results = resultSet.iterator();
129        results.forEachRemaining(result -> {
130            System.out.println(result.getObject().getClass());
131            Object object = result.getObject();
132            if (object instanceof Vertex) {
133                System.out.println(((Vertex) object).id());
134            } else if (object instanceof Edge) {
135                System.out.println(((Edge) object).id());
136            } else if (object instanceof Path) {
137                List<Object> elements = ((Path) object).objects();
138                elements.forEach(element -> {
139                    System.out.println(element.getClass());
140                    System.out.println(element);
141                });
142            } else {
143                System.out.println(object);
144            }
145        });
146
147        hugeClient.close();
148    }
149}
4.3.2 BatchExample
  1import java.util.ArrayList;
  2import java.util.List;
  3
  4import org.apache.hugegraph.driver.GraphManager;
  5import org.apache.hugegraph.driver.HugeClient;
  6import org.apache.hugegraph.driver.SchemaManager;
  7import org.apache.hugegraph.structure.graph.Edge;
  8import org.apache.hugegraph.structure.graph.Vertex;
  9
 10public class BatchExample {
 11
 12    public static void main(String[] args) {
 13        // If connect failed will throw a exception.
 14        HugeClient hugeClient = HugeClient.builder("http://localhost:8080",
 15                                                "DEFAULT",
 16                                                "hugegraph")
 17                                          .configUser("username", "password")
 18                                          // 这是示例,生产环境需要使用安全的凭证
 19                                          .build();
 20
 21        SchemaManager schema = hugeClient.schema();
 22
 23        schema.propertyKey("name").asText().ifNotExist().create();
 24        schema.propertyKey("age").asInt().ifNotExist().create();
 25        schema.propertyKey("lang").asText().ifNotExist().create();
 26        schema.propertyKey("date").asDate().ifNotExist().create();
 27        schema.propertyKey("price").asInt().ifNotExist().create();
 28
 29        schema.vertexLabel("person")
 30              .properties("name", "age")
 31              .primaryKeys("name")
 32              .ifNotExist()
 33              .create();
 34
 35        schema.vertexLabel("person")
 36              .properties("price")
 37              .nullableKeys("price")
 38              .append();
 39
 40        schema.vertexLabel("software")
 41              .properties("name", "lang", "price")
 42              .primaryKeys("name")
 43              .ifNotExist()
 44              .create();
 45
 46        schema.indexLabel("softwareByPrice")
 47              .onV("software").by("price")
 48              .range()
 49              .ifNotExist()
 50              .create();
 51
 52        schema.edgeLabel("knows")
 53              .link("person", "person")
 54              .properties("date")
 55              .ifNotExist()
 56              .create();
 57
 58        schema.edgeLabel("created")
 59              .link("person", "software")
 60              .properties("date")
 61              .ifNotExist()
 62              .create();
 63
 64        schema.indexLabel("createdByDate")
 65              .onE("created").by("date")
 66              .secondary()
 67              .ifNotExist()
 68              .create();
 69
 70        // get schema object by name
 71        System.out.println(schema.getPropertyKey("name"));
 72        System.out.println(schema.getVertexLabel("person"));
 73        System.out.println(schema.getEdgeLabel("knows"));
 74        System.out.println(schema.getIndexLabel("createdByDate"));
 75
 76        // list all schema objects
 77        System.out.println(schema.getPropertyKeys());
 78        System.out.println(schema.getVertexLabels());
 79        System.out.println(schema.getEdgeLabels());
 80        System.out.println(schema.getIndexLabels());
 81
 82        GraphManager graph = hugeClient.graph();
 83
 84        Vertex marko = new Vertex("person").property("name", "marko")
 85                                           .property("age", 29);
 86        Vertex vadas = new Vertex("person").property("name", "vadas")
 87                                           .property("age", 27);
 88        Vertex lop = new Vertex("software").property("name", "lop")
 89                                           .property("lang", "java")
 90                                           .property("price", 328);
 91        Vertex josh = new Vertex("person").property("name", "josh")
 92                                          .property("age", 32);
 93        Vertex ripple = new Vertex("software").property("name", "ripple")
 94                                              .property("lang", "java")
 95                                              .property("price", 199);
 96        Vertex peter = new Vertex("person").property("name", "peter")
 97                                           .property("age", 35);
 98
 99        Edge markoKnowsVadas = new Edge("knows").source(marko).target(vadas)
100                                                .property("date", "2016-01-10");
101        Edge markoKnowsJosh = new Edge("knows").source(marko).target(josh)
102                                               .property("date", "2013-02-20");
103        Edge markoCreateLop = new Edge("created").source(marko).target(lop)
104                                                 .property("date",
105                                                           "2017-12-10");
106        Edge joshCreateRipple = new Edge("created").source(josh).target(ripple)
107                                                   .property("date",
108                                                             "2017-12-10");
109        Edge joshCreateLop = new Edge("created").source(josh).target(lop)
110                                                .property("date", "2009-11-11");
111        Edge peterCreateLop = new Edge("created").source(peter).target(lop)
112                                                 .property("date",
113                                                           "2017-03-24");
114
115        List<Vertex> vertices = new ArrayList<>();
116        vertices.add(marko);
117        vertices.add(vadas);
118        vertices.add(lop);
119        vertices.add(josh);
120        vertices.add(ripple);
121        vertices.add(peter);
122
123        List<Edge> edges = new ArrayList<>();
124        edges.add(markoKnowsVadas);
125        edges.add(markoKnowsJosh);
126        edges.add(markoCreateLop);
127        edges.add(joshCreateRipple);
128        edges.add(joshCreateLop);
129        edges.add(peterCreateLop);
130
131        vertices = graph.addVertices(vertices);
132        vertices.forEach(vertex -> System.out.println(vertex));
133
134        edges = graph.addEdges(edges, false);
135        edges.forEach(edge -> System.out.println(edge));
136
137        hugeClient.close();
138    }
139}

4.4 运行 Example

  1. 启动 HugeGraph Server,在图空间 DEFAULT 中准备名为 hugegraph 的测试图。
  2. 将 Maven 工程的 JDK 设为 17,把所选示例中 HugeClient.builder(...) 和 configUser(...) 的 Server 地址、图空间、图名和凭据改为实际配置。 Server 未开启鉴权时,省略 configUser(...)。
  3. 在 IDE 中运行 SingleExample.main() 或 BatchExample.main()。两个示例都会创建 Schema 和图数据、打印结果并关闭客户端。 请使用测试图,已有 Schema 或数据可能影响重复运行。

本文的代码都是java语言写的,但其风格与gremlin(groovy)是非常类似的。用户只需要把代码中的变量声明替换成def或直接去掉, 就能将java代码转变为groovy;另外就是每一行语句最后可以不加分号,groovy认为一行就是一条语句。

用户在HugeGraph-Hubble中编写的gremlin(groovy)可以参考本文的java代码,下面会举出几个例子。

本文以 Toolchain master(Client 1.8.0)为准。请先按上方快速入门准备对应依赖; 能力探测等新增接口不能直接用于旧版 Client。

5 HugeClient 构造与操作入口

HugeGraph-Client 是操作 graph 的总入口,用户必须先创建出 HugeGraph-Client 对象,与 HugeGraph-Server 建立连接(伪连接)后,才能获取到 schema、graph 以及 gremlin 的操作入口对象。

HugeGraph-Client 连接服务端已有的图。构造器支持传入 GraphSpace;使用双参数构造器或传入空值时,GraphSpace 默认为 DEFAULT。

1// HugeGraphServer 地址:"http://localhost:8080"
2// 图的名称:"hugegraph"
3HugeClient hugeClient = HugeClient.builder("http://localhost:8080", "hugegraph")
4                                //.builder("http://localhost:8080", "graphSpaceName", "hugegraph")
5                                  .configTimeout(20) // 默认 20s 超时
6                                  // .configUser("username", "password") // 服务端启用认证时配置
7                                  .build();

上述创建 HugeClient 的过程如果失败会抛出异常,用户需要 try-catch。如果成功则继续获取 schema、graph 以及 gremlin 的 manager。

在HugeGraph - Hubble中通过gremlin来操作时,不需要使用HugeClient,可以忽略。

5.1 构造器选项

构造器支持下列选项。所有超时参数的单位都是秒,内部会转换为毫秒。

interfacedescriptiondefault
configUrl(String url)服务端地址,通常已经通过 builder(...) 传入必填
configGraph(String graph)图名称,通常已经通过 builder(...) 传入必填
configGraphSpace(String graphSpace)GraphSpace 名称,传入 null 或空值时回退为 DEFAULTDEFAULT
configUser(String username, String password)服务端用户名和密码,传入 null 时按空字符串处理空,不开启认证
configToken(String token)使用 Token 代替用户名和密码空
configTimeout(int seconds)请求超时,建议使用正数秒值20
configConnectTimeout(Integer seconds)连接超时,不设置时沿用 configTimeout未设置
configReadTimeout(Integer seconds)读取超时,不设置时沿用 configTimeout未设置
configPool(int maxConns, int maxConnsPerRoute)连接池大小,任意一项传入 0 时恢复其默认值4 x CPU 数,2 x CPU 数
configIdleTime(int seconds)空闲连接保持时间,必须大于 030
configSSL(String trustStoreFile, String trustStorePassword)HTTPS 连接使用的信任库空
configHttpBuilder(Consumer<OkHttpClient.Builder> consumer)回调,用于进一步定制底层的 OkHttp 客户端无
graphRequired(boolean graphRequired)build() 是否拒绝空的 url 或图名称true

当前 master 的 configTimeout(0) 存在单位换算缺陷,会得到 20,000 秒而非默认的 20 秒。 保持默认值时省略该调用,或显式使用 configTimeout(20);不要用 0 恢复默认值。

调用 build() 时,客户端会读取服务端的 API 版本,超出 [0.38, 0.81) 范围时报错。

5.2 操作入口

除 schema、graph 和 gremlin 外,HugeClient 还提供下列入口。图级别的入口只有在指定了图名称时才可用;如果创建客户端时图名称为空,这些入口会返回 null,直到调用 assignGraph(graphSpace, graph) 为止。

interfacereturnsscopedescription
schema()SchemaManagergraph管理 PropertyKey、VertexLabel、EdgeLabel 和 IndexLabel
graph()GraphManagergraph单条或批量地增删改查顶点和边
gremlin()GremlinManagergraph同步执行 Gremlin 语句,或作为异步任务提交
cypher()CypherManagergraph同步执行 Cypher 语句,或作为异步任务提交
traverser()TraverserManagergraphRESTful 遍历,如最短路径、k-out、k-neighbor、交叉点等
variables()VariablesManagergraph获取、设置、列出和删除图变量
job()JobManagergraph重建 VertexLabel、EdgeLabel 或 IndexLabel 的索引
task()TaskManagergraph列出、获取、取消、删除异步任务,或等待其完成
computer()ComputerManagergraph创建、取消、列出和获取 computer 任务
graphs()GraphsManagergraphspace创建、克隆、列出、重载、清空和删除图,读取和设置图的模式
graphSpace()GraphSpaceManagerserver管理 GraphSpace,详见第 8 节
auth()AuthManagerserver管理 user、group、target、belong 和 access
metrics()MetricsManagerserver读取后端、系统和统计指标
versionManager()VersionManagerserver读取服务端的 core、gremlin 和 API 版本

客户端还会报告所连服务端支持的能力,调用方可以据此判断,而不必解析版本号:supportsGraphSpace()、supportsCypher()、supportsGraphCreate()、supportsDefaultRole() 和 isServerAuthEnabled()。

6 元数据管理 (SchemaManager)

6.1 SchemaManager

SchemaManager 用于管理 HugeGraph 中的四种元数据,分别是 PropertyKey(属性类型)、VertexLabel(顶点类型)、EdgeLabel(边类型)和 IndexLabel(索引标签)。在定义元数据信息之前必须先创建 SchemaManager 对象。

用户可使用如下方法获得 SchemaManager 对象:

1SchemaManager schema = hugeClient.schema()

在HugeGraph-Hubble中通过gremlin创建schema对象:

1schema = graph.schema()

下面分别介绍四种元数据的定义过程。

6.2 PropertyKey

6.2.1 接口及参数介绍

PropertyKey 用来规范顶点和边的属性的约束,暂不支持定义属性的属性。

PropertyKey 允许定义的约束信息包括:name、datatype、cardinality、aggregateType、writeType、userdata,下面逐一介绍。

  • name: 属性的名字,用来区分不同的 PropertyKey,不允许有同名的属性;
interfaceparammust set
propertyKey(String name)namey
  • datatype:属性值类型,必须从下表中选择符合具体业务场景的一项显式设置;
interfaceJava Class
asText()String
asInt()Integer
asDate()Date
asUUID()UUID
asBoolean()Boolean
asByte()Byte
asBlob()Byte[]
asDouble()Double
asFloat()Float
asLong()Long
  • cardinality:属性值是单值还是多值,多值的情况下又分为允许有重复值和不允许有重复值,该项默认为 single,如有必要可从下表中选择一项设置;
interfacecardinalitydescription
valueSingle()singlesingle value
valueList()listmulti-values that allow duplicate value
valueSet()setmulti-values that not allow duplicate value
  • aggregateType:同一属性被重复写入时的合并方式,默认为 none,即保留最后写入的值。数值类的选项要求属性为数字类型;
interfaceaggregateTypedescription
calcSum()sum对写入的值累加
calcMax()max保留最大值
calcMin()min保留最小值
calcOld()old保留首次写入的值,忽略后续更新

aggregateType(AggregateType type) 可以直接设置该项,传入 AggregateType.NONE 即恢复默认。

  • writeType:属性属于 OLTP 图数据还是 OLAP 计算结果,对于 OLAP 还区分是否带索引,默认为 oltp;
writeTypedescription
OLTP普通图属性
OLAP_COMMON不带索引的 OLAP 属性
OLAP_SECONDARY带二级索引的 OLAP 属性
OLAP_RANGE带范围索引的 OLAP 属性
interfacedescription
writeType(WriteType writeType)使用枚举值设置写入类型
writeType(String name)使用枚举名设置写入类型
  • userdata:用户可以自己添加一些约束或额外信息,然后自行检查传入的属性是否满足约束,或者必要的时候提取出额外信息
interfacedescription
userdata(String key, Object value)The same key, the latter will cover the former
6.2.2 创建 PropertyKey
1schema.propertyKey("name").asText().valueSet().ifNotExist().create()

在HugeGraph-Hubble中通过gremlin创建上述PropertyKey对象的语法完全一致,如果用户没有定义出schema变量,应该这样写:

1graph.schema().propertyKey("name").asText().valueSet().ifNotExist().create()

以下的示例中,gremlin与java的语法完全一致,不再赘述。

  • ifNotExist():为 create 添加判断机制,若当前 PropertyKey 已经存在则不再创建,否则创建该属性。若不添加判断,在 properkey 已存在的情况下会抛出异常信息,下同,不再赘述。
6.2.3 删除 PropertyKey
1schema.propertyKey("name").remove()
6.2.4 查询 PropertyKey
1// 获取 PropertyKey 对象
2schema.getPropertyKey("name")
3
4// 获取 PropertyKey 属性
5schema.getPropertyKey("name").cardinality()
6schema.getPropertyKey("name").dataType()
7schema.getPropertyKey("name").name()
8schema.getPropertyKey("name").userdata()

6.3 VertexLabel

6.3.1 接口及参数介绍

VertexLabel 用来定义顶点类型,描述顶点的约束信息:

VertexLabel 允许定义的约束信息包括:name、idStrategy、properties、primaryKeys、nullableKeys 和 ttl,下面逐一介绍。

  • name: 属性的名字,用来区分不同的 VertexLabel,不允许有同名的属性;
interfaceparammust set
vertexLabel(String name)namey
  • idStrategy: 每一个 VertexLabel 都可以选择自己的 Id 策略,目前有三种策略供选择,即 Automatic(自动生成)、Customize(用户传入)和 PrimaryKey(主属性键)。其中 Automatic 使用 Snowflake 算法生成 Id,Customize 需要用户自行传入字符串或数字类型的 Id,PrimaryKey 则允许用户从 VertexLabel 的属性中选择若干主属性作为区分的依据,HugeGraph 内部会根据主属性的值拼接生成 Id。idStrategy 默认使用 Automatic 的,但如果用户没有显式设置 idStrategy 又调用了 primaryKeys(…) 方法设置了主属性,则 idStrategy 将自动使用 PrimaryKey;
interfaceidStrategydescription
useAutomaticIdAUTOMATICgenerate id automatically by Snowflake algorithm
useCustomizeStringIdCUSTOMIZE_STRINGpassed id by user, must be string type
useCustomizeNumberIdCUSTOMIZE_NUMBERpassed id by user, must be number type
useCustomizeUuidIdCUSTOMIZE_UUIDpassed id by user, must be UUID type
usePrimaryKeyIdPRIMARY_KEYchoose some important prop as primary key to splice id
  • properties: 定义顶点的属性,传入的参数是 PropertyKey 的 name
interfacedescription
properties(String… properties)allow to pass multi props
  • primaryKeys: 当用户选择了 PrimaryKey 的 Id 策略时,需要从 VertexLabel 的属性中选择若干主属性作为区分的依据;
interfacedescription
primaryKeys(String… keys)allow to choose multi prop as primaryKeys

需要注意的是,Id 策略的选择与 primaryKeys 的设置有一些相互约束,不能随意调用,约束关系见下表:

useAutomaticIduseCustomizeStringIduseCustomizeNumberIdusePrimaryKeyId
unset primaryKeysAUTOMATICCUSTOMIZE_STRINGCUSTOMIZE_NUMBERERROR
set primaryKeysERRORERRORERRORPRIMARY_KEY

客户端自身只校验 Id 策略是否被重复设置,因此在同一个构造器上调用两个上述方法会在本地报错。上表中的组合由服务端校验。

  • nullableKeys: 对于通过 properties(…) 方法设置过的属性,默认全都是不可为空的,也就是在创建顶点时该属性必须赋值,这样可能对用户数据提出了太过严格的完整性要求。为避免这样的强约束,用户可以通过 本方法设置若干属性为可空的,这样添加顶点时该属性可以不赋值。
interfacedescription
nullableKeys(String… properties)allow to pass multi props

注意:primaryKeys 和 nullableKeys 不能有交集,因为一个属性不能既作为主属性,又是可空的。

  • ttl:该类型顶点的存活时间,默认为 0,即永不过期。客户端会拒绝负值。默认从顶点写入的时刻开始计时;设置 ttlStartTime 后,改为从该 label 的某个日期属性开始计时。
interfacedescription
ttl(long ttl)设置存活时间,0 表示不过期
ttlStartTime(String property)指定计时起点所用的日期属性
  • enableLabelIndex:用户可以指定是否需要为 label 创建索引。不创建则无法全局搜索指定 label 的顶点和边,创建则可以全局搜索,做类似于g.V().hasLabel('person'), g.E().has('label', 'person')这样的查询, 但是插入数据时性能上会更加慢,并且需要占用更多的存储空间。此项默认为 true。
interfacedescription
enableLabelIndex(boolean enable)Whether to create a label index
  • userdata:用户可以自己添加一些约束或额外信息,然后自行检查传入的属性是否满足约束,或者必要的时候提取出额外信息
interfacedescription
userdata(String key, Object value)The same key, the latter will cover the former
6.3.2 创建 VertexLabel
 1// 使用 Automatic 的 Id 策略
 2schema.vertexLabel("person").properties("name", "age").ifNotExist().create();
 3schema.vertexLabel("person").useAutomaticId().properties("name", "age").ifNotExist().create();
 4
 5// 使用 Customize_String 的 Id 策略
 6schema.vertexLabel("person").useCustomizeStringId().properties("name", "age").ifNotExist().create();
 7// 使用 Customize_Number 的 Id 策略
 8schema.vertexLabel("person").useCustomizeNumberId().properties("name", "age").ifNotExist().create();
 9// 使用 Customize_Uuid 的 Id 策略
10schema.vertexLabel("person").useCustomizeUuidId().properties("name", "age").ifNotExist().create();
11
12// 使用 PrimaryKey 的 Id 策略
13schema.vertexLabel("person").properties("name", "age").primaryKeys("name").ifNotExist().create();
14schema.vertexLabel("person").usePrimaryKeyId().properties("name", "age").primaryKeys("name").ifNotExist().create();
6.3.3 追加 VertexLabel

VertexLabel 是可以追加约束的,不过仅限 properties 和 nullableKeys,而且追加的属性也必须添加到 nullableKeys 集合中。

1schema.vertexLabel("person").properties("price").nullableKeys("price").append();
6.3.4 删除 VertexLabel
1schema.vertexLabel("person").remove();
6.3.5 查询 VertexLabel
 1// 获取 VertexLabel 对象
 2schema.getVertexLabel("name")
 3
 4// 获取 property key 属性
 5schema.getVertexLabel("person").idStrategy()
 6schema.getVertexLabel("person").primaryKeys()
 7schema.getVertexLabel("person").name()
 8schema.getVertexLabel("person").properties()
 9schema.getVertexLabel("person").nullableKeys()
10schema.getVertexLabel("person").userdata()
11schema.getVertexLabel("person").ttl()
12schema.getVertexLabel("person").ttlStartTime()

6.4 EdgeLabel

6.4.1 接口及参数介绍

EdgeLabel 用来定义边类型,描述边的约束信息。

EdgeLabel 允许定义的约束信息包括:name、sourceLabel、targetLabel、frequency、properties、sortKeys、nullableKeys 和 ttl,下面逐一介绍。

  • name: 属性的名字,用来区分不同的 EdgeLabel,不允许有同名的属性;
interfaceparammust set
edgeLabel(String name)namey
  • sourceLabel 和 targetLabel: 边连接的源顶点类型名和目标顶点类型名,两者都设置等同于声明一组连接。

  • link: EdgeLabel 内部保存的是一组源顶点和目标顶点的组合,因此 link(...) 可以多次调用,让同一种边连接多组顶点类型。一旦通过这种方式添加过组合,sourceLabel(...) 和 targetLabel(...) 就会被拒绝;同时 sourceLabel() 和 targetLabel() 这两个取值方法只在恰好有一组组合时可用,需要读取全部组合时请使用 links()。

interfaceparammust set
link(String sourceLabel, String targetLabel)sourceLabel, targetLabely,或设置下面两项
sourceLabel(String label)labely,除非已使用 link()
targetLabel(String label)labely,除非已使用 link()
  • frequency: 字面意思是频率,表示在两个具体的顶点间某个关系出现的次数,可以是单次(single)或多次(frequency),默认为 single;
interfacefrequencydescription
singleTime()singlea relationship can only occur once
multiTimes()multiplea relationship can occur many times
  • properties: 定义边的属性
interfacedescription
properties(String… properties)allow to pass multi props
  • sortKeys: 当 EdgeLabel 的 frequency 为 multiple 时,需要某些属性来区分这多次的关系,故引入了 sortKeys(排序键);
interfacedescription
sortKeys(String… keys)allow to choose multi prop as sortKeys
  • nullableKeys: 与顶点中的 nullableKeys 概念一致,不再赘述

注意:sortKeys 和 nullableKeys 也不能有交集。

  • ttl:与顶点中的 ttl 概念一致,同样提供 ttl(long ttl) 和 ttlStartTime(String property) 方法,默认值同样为 0。

  • edge label type:EdgeLabel 默认为普通类型,也可以声明为一族边类型的父类型、某个父类型的子类型,或者通用类型:

interfaceedgeLabelTypedescription
asBase()PARENT将该 label 声明为父类型
withBase(String parentLabel)SUB将该 label 声明为 parentLabel 的子类型
asGeneral()GENERAL将该 label 声明为通用类型
  • enableLabelIndex:与顶点中的 enableLabelIndex 概念一致,不再赘述

  • userdata:用户可以自己添加一些约束或额外信息,然后自行检查传入的属性是否满足约束,或者必要的时候提取出额外信息

interfacedescription
userdata(String key, Object value)The same key, the latter will cover the former
6.4.2 创建 EdgeLabel
1schema.edgeLabel("knows").link("person", "person").properties("date").ifNotExist().create();
2schema.edgeLabel("created").multiTimes().link("person", "software").properties("date").sortKeys("date").ifNotExist().create();
6.4.3 追加 EdgeLabel
1schema.edgeLabel("knows").properties("price").nullableKeys("price").append();
6.4.4 删除 EdgeLabel
1schema.edgeLabel("knows").remove();
6.4.5 查询 EdgeLabel
 1// 获取 EdgeLabel 对象
 2schema.getEdgeLabel("knows")
 3
 4// 获取 property key 属性
 5schema.getEdgeLabel("knows").frequency()
 6schema.getEdgeLabel("knows").sourceLabel()
 7schema.getEdgeLabel("knows").targetLabel()
 8schema.getEdgeLabel("knows").sortKeys()
 9schema.getEdgeLabel("knows").name()
10schema.getEdgeLabel("knows").properties()
11schema.getEdgeLabel("knows").nullableKeys()
12schema.getEdgeLabel("knows").userdata()
13schema.getEdgeLabel("knows").ttl()
14schema.getEdgeLabel("knows").ttlStartTime()
15schema.getEdgeLabel("knows").edgeLabelType()
16// 全部的源顶点和目标顶点组合,存在多组时也可安全调用
17schema.getEdgeLabel("knows").links()

6.5 IndexLabel

6.5.1 接口及参数介绍

IndexLabel 用来定义索引类型,描述索引的约束信息,主要是为了方便查询。

IndexLabel 允许定义的约束信息包括:name、baseType、baseValue、indexFields、indexType,下面逐一介绍。

  • name: 属性的名字,用来区分不同的 IndexLabel,不允许有同名的属性;
interfaceparammust set
indexLabel(String name)namey
  • baseType: 表示要为 VertexLabel 还是 EdgeLabel 建立索引, 与下面的 baseValue 配合使用;

  • baseValue: 指定要建立索引的 VertexLabel 或 EdgeLabel 的名称;

interfaceparamdescription
onV(String baseValue)baseValuebuild index for VertexLabel: ‘baseValue’
onE(String baseValue)baseValuebuild index for EdgeLabel: ‘baseValue’
  • indexFields: 要在哪些属性上建立索引,可以是为多列建立联合索引;
interfaceparamdescription
by(String… fields)filesallow to build index for multi fields for secondary index
  • indexType: 建立的索引类型,目前支持五种,即 Secondary、Range、Search、Shard 和 Unique。
    • Secondary 支持精确匹配的二级索引,允许建立联合索引,联合索引支持索引前缀搜索
      • 单个属性,支持相等查询,比如:person 顶点的 city 属性的二级索引,可以用g.V().has("city", "北京") 查询"city 属性值是北京"的全部顶点
      • 联合索引,支持前缀查询和相等查询,比如:person 顶点的 city 和 street 属性的联合索引,可以用g.V().has ("city", "北京").has('street', '中关村街道') 查询"city属性值是北京且street属性值是中关村"的全部顶点,或者g.V() .has("city", "北京")查询"city 属性值是北京"的全部顶点

      secondary index 的查询都是基于"是"或者"相等"的查询条件,不支持"部分匹配"

    • Range 支持数值类型的范围查询
      • 必须是单个数字或者日期属性,比如:person 顶点的 age 属性的范围索引,可以用g.V().has("age", P.gt(18)) 查询"age属性值大于18"的顶点。除了P.gt()以外,还支持P.gte(), P.lte(), P.lt(), P.eq(), P.between(), P.inside()和P.outside()等
    • Search 支持全文检索的索引
      • 必须是单个文本属性,比如:person 顶点的 address 属性的全文索引,可以用g.V().has("address", Text .contains('大厦')查询"address 属性中包含大厦"的全部顶点

      search index 的查询是基于"是"或者"包含"的查询条件

    • Shard 支持前缀匹配 + 数字范围查询的索引
      • N 个属性的分片索引,支持前缀相等情况下的范围查询,比如:person 顶点的 city 和 age 属性的分片索引,可以用g.V().has ("city", "北京").has("age", P.between(18, 30)) 查询"city 属性是北京且年龄大于等于 18 小于 30"的全部顶点
      • shard index N 个属性全是文本属性时,等价于 secondary index
      • shard index 只有单个数字或者日期属性时,等价于 range index

      shard index 可以有任意数字或者日期属性,但是查询时最多只能提供一个范围查找条件,且该范围查找条件的属性的前缀属性都是相等查询条件

    • Unique 支持属性值唯一性约束,即可以限定属性的值不重复,允许联合索引,但不支持查询
      • 单个或者多个属性的唯一性索引,不可用来查询,只可对属性的值进行限定,当出现重复值时将报错
interfaceindexTypedescription
secondary()Secondarysupport prefix search
range()Rangesupport range(numeric or date type) search
search()Searchsupport full text search
shard()Shardsupport prefix + range(numeric or date type) search
unique()Uniquesupport unique props value, not support search
6.5.2 创建 IndexLabel

以下示例假定已创建带 name、age 的 person 顶点类型,以及带 date 的 created 边类型。 先补充索引所需属性;id 是业务属性,与顶点的内部 ID 不同。

 1schema.propertyKey("lived").asText().ifNotExist().create();
 2schema.propertyKey("city").asText().ifNotExist().create();
 3schema.propertyKey("id").asInt().ifNotExist().create();
 4schema.vertexLabel("person").properties("lived", "city", "id")
 5      .nullableKeys("lived", "city", "id").append();
 6
 7schema.indexLabel("personByAge").onV("person").by("age").range().ifNotExist().create();
 8schema.indexLabel("createdByDate").onE("created").by("date").secondary().ifNotExist().create();
 9schema.indexLabel("personByLived").onV("person").by("lived").search().ifNotExist().create();
10schema.indexLabel("personByCityAndAge").onV("person").by("city", "age").shard().ifNotExist().create();
11schema.indexLabel("personById").onV("person").by("id").unique().ifNotExist().create();
6.5.3 删除 IndexLabel
1schema.indexLabel("personByAge").remove()
6.5.4 查询 IndexLabel
1// 获取 IndexLabel 对象
2schema.getIndexLabel("personByAge")
3
4// 获取 property key 属性
5schema.getIndexLabel("personByAge").baseType()
6schema.getIndexLabel("personByAge").baseValue()
7schema.getIndexLabel("personByAge").indexFields()
8schema.getIndexLabel("personByAge").indexType()
9schema.getIndexLabel("personByAge").name()

7 图数据操作 (GraphManager)

7.1 Vertex

顶点是构成图的最基本元素,一个图中可以有非常多的顶点。下面给出一个添加顶点的例子:

1Vertex marko = graph.addVertex(T.LABEL, "person", "name", "marko", "age", 29);
2Vertex lop = graph.addVertex(T.LABEL, "software", "name", "lop", "lang", "java", "price", 328);
  • 添加顶点的关键是顶点属性,添加顶点函数的参数个数必须为偶数,且满足key1 -> val1, key2 -> val2 ···的顺序排列,键值对之间的顺序是自由的。
  • 参数中必须包含一对特殊的键值对,就是T.LABEL -> "val",用来定义该顶点的类别,以便于程序从缓存或后端获取到该 VertexLabel 的 schema 定义,然后做后续的约束检查。例子中的 label 定义为 person。T.LABEL 就是常量 "label",直接传入该字符串效果相同。
  • 如果顶点类型的 Id 策略为 AUTOMATIC,则不允许用户传入 id 键值对。
  • 如果顶点类型的 Id 策略为 CUSTOMIZE_STRING,则用户需要自己传入 String 类型 id 的值,键值对形如:T.ID, "123456"。
  • 如果顶点类型的 Id 策略为 CUSTOMIZE_NUMBER,则用户需要自己传入 Number 类型 id 的值,键值对形如:T.ID, 123456。
  • 如果顶点类型的 Id 策略为 PRIMARY_KEY,参数还必须全部包含该primaryKeys对应属性的名和值,如果不设置会抛出异常。比如之前person的primaryKeys是name,例子中就设置了name的值为marko。
  • 对于非 nullableKeys 的属性,必须要赋值。
  • 剩下的参数就是顶点其他属性的设置,但并非必须。
  • 调用addVertex方法后,顶点会立刻被插入到后端存储系统中。

7.2 Edge

有了点,还需要边才能构成完整的图。下面给出一个添加边的例子:

1Edge knows1 = marko.addEdge("knows", vadas, "city", "Beijing");
  • 由(源)顶点来调用添加边的函数,函数第一个参数为边的 label,第二个参数是目标顶点,这两个参数的位置和顺序是固定的。后续的参数就是key1 -> val1, key2 -> val2 ···的顺序排列,设置边的属性,键值对顺序自由。
  • 源顶点和目标顶点必须符合 EdgeLabel 中 source-label 和 target-label 的定义,不能随意添加。
  • 对于非 nullableKeys 的属性,必须要赋值。

注意:当 frequency 为 multiple 时必须要设置 sortKeys 对应属性类型的值。

8 图空间管理 (GraphSpace)

Client 支持管理一个物理部署中的多个 GraphSpace,每个 GraphSpace 可以包含多个图。不指定 GraphSpace 时使用 DEFAULT。

GraphSpace 需要服务端 core 版本不低于 1.7.0。连接更早的服务端时,客户端会退回到 legacy 模式,此时 hugeClient.supportsGraphSpace() 返回 false。

8.1 创建GraphSpace

 1GraphSpaceManager spaceManager = hugeClient.graphSpace();
 2
 3// 定义 GraphSpace 配置
 4GraphSpace graphSpace = new GraphSpace();
 5graphSpace.setName("myGraphSpace");
 6graphSpace.setDescription("Business data graph space");
 7graphSpace.setMaxGraphNumber(10);  // 最大图数量
 8graphSpace.setMaxRoleNumber(100);  // 最大角色数量
 9
10// 创建 GraphSpace
11spaceManager.createGraphSpace(graphSpace);

8.2 GraphSpace 接口汇总

类别接口描述
Manager - 查询listGraphSpace()获取所有 GraphSpace 名称
listProfile() / listProfile(String prefix)获取 GraphSpace 概要
getGraphSpace(String name)获取指定 GraphSpace
getDefault()获取默认 GraphSpace
Manager - 创建/更新createGraphSpace(GraphSpace)创建 GraphSpace
updateGraphSpace(GraphSpace)更新配置
setDefault(String name)设置默认 GraphSpace
Manager - 删除deleteGraphSpace(String name)删除指定 GraphSpace
Manager - 默认角色setDefaultRole(String name, String user, String role)授予默认角色,可用第四个参数限定到某个图
checkDefaultRole(String name, String user, String role)检查默认角色,可用第四个参数限定到某个图
deleteDefaultRole(String name, String user, String role)撤销默认角色,可用第四个参数限定到某个图
GraphSpace - 属性getName() / getNickname() / getDescription()获取名称/昵称/描述
getGraphNumberUsed() / getRoleNumberUsed()获取已使用的图数量/角色数量
getCpuUsed() / getMemoryUsed() / getStorageUsed()获取已使用的资源
getCreateTime() / getUpdateTime()获取创建时间/更新时间
GraphSpace - 配置setDescription(String) / setNickname(String)设置描述/昵称
setMaxGraphNumber(int) / setMaxRoleNumber(int)设置最大图数量/角色数量
setCpuLimit(int) / setMemoryLimit(int) / setStorageLimit(int)设置资源配额
setConfigs(Map<String, Object>)设置额外的配置项

2 - HugeGraph Python 客户端快速上手

hugegraph-python-client 是 Apache HugeGraph 的 Python SDK。它支持管理 Schema、读写图数据、执行 Gremlin 查询、进行 OLTP 实时图遍历以及 提交异步 OLAP 全图计算任务。HugeGraph-LLM 和 HugeGraph-ML 也依赖该客户端进行图数据库交互。

客户端源码位于 hugegraph-ai 仓库的 hugegraph-python-client/ 目录下,导入包名为 pyhugegraph。

环境要求

  • Python >= 3.12(支持 Python 3.12–3.14)。
  • HugeGraph Server 1.5.0 或更高版本(Server 1.7+ 推荐开启 GraphSpace 模式;1.5/1.6 使用传统路由)。
  • pip 或 uv 包管理器。

运行时依赖包括 decorator、requests、urllib3 和 rich。

安装

客户端提供两种安装方式,具体取决于使用的是 PyPI 稳定发行版还是 master 分支最新的开发功能。

说明

版本与功能边界说明: 已发布的 PyPI 发行包(hugegraph-python 1.7.x)为稳定基础版本,以 CamelCase 命名风格为主(带旧版 snake_case 别名)。 本文档演示的现代特性——包括原生 snake_case API、client.olap() 全图计算算法、client.task().wait() 任务轮询等待、 client.close() 连接生命周期管理以及更新后的遍历器签名——均对齐 master 分支最新实现。 如需体验或测试这些新特性,请通过源码方式安装客户端。

PyPI 稳定版 (1.7.x)
1pip install hugegraph-python
2# 或使用 uv:
3# uv pip install hugegraph-python
源码安装 (Master)
1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai/hugegraph-python-client
3pip install -e .
Workspace 同步 (uv)
1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3uv sync --extra python-client
4source .venv/bin/activate

连接与数据写入

 1from pyhugegraph.client import PyHugeClient
 2
 3client = PyHugeClient(
 4    url="http://127.0.0.1:8080",
 5    graph="hugegraph",
 6    user="admin",
 7    pwd="admin",
 8    graphspace=None,
 9)
10
11schema = client.schema()
12schema.property_key("name").as_text().if_not_exist().create()
13schema.property_key("birthDate").as_text().if_not_exist().create()
14schema.vertex_label("Person").properties("name", "birthDate") \
15      .use_primary_key_id().primary_keys("name").if_not_exist().create()
16schema.vertex_label("Movie").properties("name") \
17      .use_primary_key_id().primary_keys("name").if_not_exist().create()
18schema.edge_label("ActedIn").source_label("Person").target_label("Movie") \
19      .if_not_exist().create()
20
21graph = client.graph()
22person = graph.add_vertex(
23    "Person", {"name": "Al Pacino", "birthDate": "1940-04-25"}
24)
25movie = graph.add_vertex("Movie", {"name": "The Godfather"})
26edge = graph.add_edge("ActedIn", person.id, movie.id, {})
27
28print(graph.get_vertex_by_id(person.id))
29print(graph.get_edge_by_id(edge.id))
30
31client.close()

客户端初始化参数

PyHugeClient(url, graph, user, pwd, graphspace=None, timeout=None, *, token=None)

参数类型默认值说明
urlstr必填HugeGraph Server 基础地址。若未携带协议前缀,会自动补齐 http://(例如 127.0.0.1:8080)。
graphstr必填目标图实例名称,为第二个位置参数。
userstr必填用户名,用于 HTTP Basic Auth 认证。
pwdstr必填密码,用于 HTTP Basic Auth 认证。
graphspacestr 或 NoneNoneGraphSpace 名称。为 None 时通过版本探测自动决定路由。
timeoutfloat、tuple[float, float] 或 NoneNone(connect, read) 超时秒数,或统一指定单个浮点数。默认值为 (0.5, 15.0)。
tokenstr 或 NoneNone显式指定 Bearer Token;提供时优先覆盖 Basic Auth 认证。

对于幂等请求,在收到 500、502、504 错误响应时最多重试 3 次(退避系数为 0.1)。异步任务轮询等待期间会自动管理截止时间预算,不额外触发重定向或 HTTP 重试。

服务端版本与 GraphSpace 路由

客户端在初始化阶段自动解析 GraphSpace 路由:

  • 显式传入非空 graphspace 时,直接启用对应的 GraphSpace 路由模式。
  • graphspace=None 时,客户端向 GET {url}/versions 发起探测以获取服务端内核版本。
  • HugeGraph Server 1.7+ 默认启用 GraphSpace 并分配至 DEFAULT。
  • HugeGraph Server 1.5 / 1.6 保持传统无 GraphSpace 路由。
  • 低于 1.5.0 的版本不支持,初始化时会抛出 RuntimeError。
  • 若版本探测失败且未显式指定 GraphSpace,客户端初始化将直接抛出异常,避免错误猜测服务端路由结构。

路由模式决定了服务端请求路径前缀:开启 GraphSpace 时为 /graphspaces/<graphspace>/graphs/<graph>/...,关闭时为 /graphs/<graph>/...。

客户端入口概览

PyHugeClient 实例维护全局共享的 HTTP Session。所有管理器均采用延迟加载并缓存复用:

访问入口管理器类功能范围
client.schema()SchemaManager属性类型、顶点类型、边类型、索引类型管理
client.graph()GraphManager顶点与边增删改查、批量写入、条件分页查询
client.gremlin()GremlinManager执行 Gremlin 查询语句
client.traverser()TraverserManager实时图遍历与路径查询(OLTP)
client.rank()RankManager实时个性化推荐排序(OLTP)
client.olap()OlapManager异步全图计算算法作业(OLAP)
client.task()TaskManager异步任务状态查询、结果轮询等待、任务取消与删除
client.graphs()GraphsManager图元数据查看、配置导出、图列表、清空全图数据
client.graphspaces()GraphspaceManager多图空间(GraphSpace)生命周期管理
client.schema_templates()SchemaTemplateManager可复用 Schema 模板管理
client.auth()AuthManager用户、用户组、目标资源、所属关系与权限管理
client.variable()VariableManager图级别持久化键值变量
client.metrics()MetricsManager服务端监控指标数据采集
client.version()VersionManager服务端及各组件版本信息
client.rest()RestClient底层 REST API 直接调用及扩展端点

常用操作

定义 Schema

Schema 构造器采用链式调用。调用 create() 执行创建,或使用 append()、eliminate()、remove() 修改已有定义:

 1schema = client.schema()
 2
 3# 属性类型:as_text / as_int / as_long / as_float / as_double / as_bool / as_date
 4# 基数模式:value_single / value_list / value_set
 5schema.property_key("age").as_int().value_single().if_not_exist().create()
 6
 7# 顶点类型:use_automatic_id / use_customize_string_id / use_primary_key_id
 8schema.vertex_label("person").properties("name", "age", "city") \
 9      .primary_keys("name").nullable_keys("city").if_not_exist().create()
10
11# 边类型:link() 快捷指定起点与终点顶点类型
12schema.edge_label("knows").link("person", "person").multi_times() \
13      .properties("date", "city").sort_keys("date").nullable_keys("city") \
14      .if_not_exist().create()
15
16# 索引类型:on_v / on_e,支持 secondary / range / search / shard / unique
17schema.index_label("personByCity").on_v("person").by("city") \
18      .secondary().if_not_exist().create()

查询 Schema

 1schema = client.schema()
 2print(schema.get_schema())            # 获取全图 Schema 结构字典
 3print(schema.get_property_keys())
 4print(schema.get_vertex_labels())
 5print(schema.get_edge_labels())
 6print(schema.get_index_labels())
 7
 8# 查询单个 Schema 定义
 9print(schema.get_property_key("name"))
10print(schema.get_vertex_label("person"))
11print(schema.get_edge_label("knows"))
12print(schema.get_index_label("personByCity"))
13
14# 边关联关系概览,格式形如 "Person--ActedIn-->Movie"
15print(schema.get_relations())

增删改查图数据

图数据 API 直接接收 Python 属性字典:

1graph = client.graph()
2graph.append_vertex(person.id, {"birthDate": "1940-04-25"})    # 追加属性
3graph.eliminate_vertex(person.id, {"birthDate": "1940-04-25"}) # 移除属性
4graph.append_edge(edge.id, {"city": "Beijing"})
5graph.eliminate_edge(edge.id, {"city": "Beijing"})
6graph.remove_edge_by_id(edge.id)
7graph.remove_vertex_by_id(person.id)

add_vertex 返回包含 id、label、type 与 properties 的 VertexData 实例。 add_edge 返回包含 id、label、type、outV、outVLabel、inV、inVLabel 与 properties 的 EdgeData 实例。

传入客户端的顶点 ID 可以是字符串、整数或 uuid.UUID 对象。布尔类型会被拦截拒绝,整数必须位于 Java 64 位有符号整型范围内。

批量导入数据

add_vertices 接收 (label, properties) 元组列表,add_edges 接收 (label, out_id, in_id, out_label, in_label, properties) 元组列表:

1graph = client.graph()
2vertices = graph.add_vertices([
3    ("person", {"name": "Alice", "age": 20}),
4    ("person", {"name": "Bob", "age": 23}),
5])
6edges = graph.add_edges([
7    ("knows", vertices[0].id, vertices[1].id, "person", "person", {"date": "2012-01-10"}),
8])

分页与条件查询

 1graph = client.graph()
 2
 3# 分页迭代查询:传入上一页返回的 next_page token 即可继续拉取下一页
 4vertices, next_page = graph.get_vertex_by_page("person", limit=10)
 5vertices, next_page = graph.get_vertex_by_page("person", limit=10, page=next_page)
 6
 7# 服务端属性条件过滤
 8older = graph.get_vertex_by_condition("person", properties={"age": "P.gt(29)"})
 9
10# 边分页查询(指定 vertex_id 时必须同时指定 direction 方向)
11edges, next_page = graph.get_edge_by_page(label="knows", limit=10)
12edges, next_page = graph.get_edge_by_page(vertex_id=person.id, direction="OUT", limit=10)
13
14# 根据 ID 列表批量查询顶点与边
15graph.get_vertices_by_id([v1.id, v2.id])
16graph.get_edges_by_id([e1.id, e2.id])

执行 Gremlin 查询

1gremlin = client.gremlin()
2result = gremlin.exec("g.V().limit(5)")
3print(result)

exec() 会根据图实例名称及解析出的 GraphSpace 自动绑定 graph 与 g 别名,并解析返回服务端响应中的 result 数据内容。

实时图遍历(OLTP)

client.traverser() 封装了服务端实时图遍历接口,支持多跳邻居、最短路径、共同邻居与相似度计算:

 1traverser = client.traverser()
 2
 3traverser.k_out(marko_id, 2)
 4traverser.k_neighbor(marko_id, 2)
 5traverser.same_neighbors(marko_id, josh_id)
 6traverser.jaccard_similarity(marko_id, josh_id)
 7traverser.shortest_path(marko_id, ripple_id, 3)
 8traverser.all_shortest_paths(marko_id, ripple_id, 3)
 9traverser.weighted_shortest_path(marko_id, ripple_id, "weight", 3)
10traverser.single_source_shortest_path(marko_id, 2)
11traverser.multi_node_shortest_path([marko_id, josh_id], max_depth=2)
12traverser.paths(marko_id, josh_id, 2)
13traverser.crosspoints(marko_id, josh_id, 2)
14traverser.rings(marko_id, 3)
15traverser.rays(marko_id, 2)
16traverser.vertices(marko_id)
17traverser.edges(edge_id)

POST 方式的遍历接口支持复杂请求体:advanced_paths、customized_paths、template_paths、customized_crosspoints 以及 fusiform_similarity。

OLAP 全图计算任务

对于全图级别的重型计算算法(如 PageRank、Louvain 社区发现、中心度计算等),请使用 client.olap()。这些作业在服务端以异步任务方式运行并通过 Task ID 进行跟踪管理:

 1# 1. 提交异步计算任务
 2receipt = client.olap().count_vertex()
 3task_id = receipt["task_id"]
 4
 5# 2. 轮询等待任务完成并获取计算结果
 6task = client.task().wait(task_id, timeout=300, poll_interval=1)
 7result = client.task().result(task)
 8print(result)
 9
10# 也可以直接使用 run() 一步完成提交、等待与结果解析:
11result = client.olap().run("count_vertex", timeout=60)

支持的 OLAP 算法

服务端提供了 17 个唯一的全图计算算法名称:

算法类别具体算法名称
图统计count_edge、count_vertex、subgraph_stat、triangle_count、rings
中心度betweenness_centrality、closeness_centrality、degree_centrality、eigenvector_centrality、stress_centrality
社区与聚类cluster_coefficient、k_core、louvain、lpa、weak_connected_component
排序与相似度page_rank、fusiform_similarity
提示

类似 page_rank 的算法会将计算出的权重属性回写到图中。在要求显式 Schema 声明的环境中,执行 PageRank 前需在参与计算的顶点类型上提前声明名为 r_rank 的可空 DOUBLE 属性。

任务生命周期管理

TaskManager 提供了对异步任务的完整管控能力:

 1task = client.task()
 2
 3# 查询任务历史列表
 4task.list_tasks(status="success", limit=10)
 5
 6# 轮询等待指定任务完成
 7record = task.wait(task_id, timeout=300, poll_interval=1)
 8
 9# 解码任务执行结果(只对序列化 JSON 解析一次)
10result = task.result(record)
11
12# 取消或删除任务
13task.cancel_task(task_id)
14task.delete_task(task_id, force=False)
  • wait(id, timeout=300, poll_interval=1) 轮询期间仅查询任务状态而不拉取大体积结果,完成后再统一获取最终产出。
  • TaskTimeoutError 仅代表客户端轮询等待超时,服务端后台运行的任务作业不会被终止。
  • 如需强行终止服务端任务,请显式调用 cancel_task(id)。

图变量、监控与元数据

 1# 图变量管理
 2variable = client.variable()
 3variable.set("owner", "mary")
 4print(variable.get("owner"))
 5print(variable.all())
 6variable.remove("owner")
 7
 8# 监控指标数据
 9metrics = client.metrics()
10metrics.get_all_basic_metrics()
11metrics.get_system_metrics()
12metrics.get_backend_metrics()
13
14# 图管理与版本
15graphs = client.graphs()
16print(graphs.list())
17print(client.version().version())

认证与权限控制

PyHugeClient 同时支持 HTTP Basic Auth 与 Bearer Token 认证:

1# 将会话切换为 Bearer Token 认证
2client.use_token("your-jwt-token")
3
4# 恢复为初始化配置的 HTTP Basic Auth 凭据
5client.use_token(None)

AuthManager 支持在 GraphSpace 隔离下管理用户、用户组、目标资源、所属关系以及操作权限:

 1auth = client.auth()
 2
 3user = auth.create_user("test_user", "password")
 4auth.modify_user(user["id"], user_email="hugegraph@apache.org")
 5auth.get_user(user["id"])
 6auth.list_users(limit=10)
 7
 8group = auth.create_group("test_group", "read only")
 9auth.modify_group(group["id"], group_description="updated")
10auth.list_groups()
11
12target = auth.create_target("target1", "hugegraph", "127.0.0.1:8080", [])
13auth.update_target(target["id"], "target1", "hugegraph", "127.0.0.1:8080", [])
14auth.list_targets()
15
16belong = auth.create_belong(user["id"], group["id"])
17auth.update_belong(belong["id"], "description")
18auth.list_belongs()
19
20access = auth.grant_accesses(group["id"], target["id"], "READ")
21auth.modify_accesses(access["id"], "description")
22auth.list_accesses()
23
24# 按照依赖反向顺序清理资源
25auth.revoke_accesses(access["id"])
26auth.delete_belong(belong["id"])
27auth.delete_target(target["id"])
28auth.delete_group(group["id"])
29auth.delete_user(user["id"])

方法命名规范与迁移说明

  • 推荐规范:新代码请统一使用 snake_case 方法名(如 add_vertex、property_key 等)。
  • 兼容保证:现有的公开 CamelCase 方法(如 addVertex、propertyKey 等)作为直接别名持续得到兼容支持。
  • 客户端生命周期:结束调用后请统一通过 client.close() 释放连接池会话资源,无需单独关闭单个 manager。
  • 返回契约:
    • 传统快捷接口 get_all_graphs()、get_version() 和 get_graph_info() 保持返回 JSON 字符串以维护向前兼容。
    • 标准现代接口 client.graphs().list()、client.version().version() 和 client.graphs().get(graph_name) 直接返回已解析的 Python 字典。
    • 带权最短路径与单源最短路径方法不再支持 max_depth 参数(服务端接口不支持);请使用 capacity、max_degree 和 skip_degree 参数进行限制。

底层 REST API 直接调用

对于批量原生接口调用或高级管理器尚未封装的扩展接口,可通过 client.rest() 直接访问完整 REST 接口面:

1rest = client.rest()
2print(rest.vertex.list(label="person", offset=0, limit=20))
3print(rest.task.list(status="success", page="", limit=20))

下表列出与服务端完全对齐的 194 个底层 REST 端点:

Python REST entryMethodPathQuery parameters
rest.access.create()POST/graphspaces/{graphspace}/auth/accesses—
rest.access.delete()DELETE/graphspaces/{graphspace}/auth/accesses/{id}—
rest.access.get()GET/graphspaces/{graphspace}/auth/accesses/{id}—
rest.access.list()GET/graphspaces/{graphspace}/auth/accessesgroup, target, limit
rest.access.update()PUT/graphspaces/{graphspace}/auth/accesses/{id}—
rest.adamic_adar.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/adamicadarvertex, other, direction, label, max_degree, limit
rest.algorithm.post()POST/graphspaces/{graphspace}/graphs/{graph}/jobs/algorithm/{name}—
rest.all_shortest_paths.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/allshortestpathssource, target, direction, label, max_depth, max_degree, skip_degree, with_vertex, with_edge, capacity
rest.arthas.start_arthas()PUT/arthas—
rest.belong.create()POST/graphspaces/{graphspace}/auth/belongs—
rest.belong.delete()DELETE/graphspaces/{graphspace}/auth/belongs/{id}—
rest.belong.get()GET/graphspaces/{graphspace}/auth/belongs/{id}—
rest.belong.list()GET/graphspaces/{graphspace}/auth/belongsuser, group, limit
rest.belong.update()PUT/graphspaces/{graphspace}/auth/belongs/{id}—
rest.computer.post()POST/graphspaces/{graphspace}/graphs/{graph}/jobs/computer/{name}—
rest.count.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/count—
rest.crosspoints.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/crosspointssource, target, direction, label, max_depth, max_degree, capacity, limit
rest.customized_crosspoints.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/customizedcrosspoints—
rest.customized_paths.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/customizedpaths—
rest.cypher.post()POST/graphspaces/{graphspace}/graphs/{graph}/cypher—
rest.cypher.query()GET/graphspaces/{graphspace}/graphs/{graph}/cyphercypher
rest.edge.create()POST/graphspaces/{graphspace}/graphs/{graph}/graph/edges—
rest.edge.create_batch()POST/graphspaces/{graphspace}/graphs/{graph}/graph/edges/batchcheck_vertex
rest.edge.delete()DELETE/graphspaces/{graphspace}/graphs/{graph}/graph/edges/{id}label
rest.edge.get()GET/graphspaces/{graphspace}/graphs/{graph}/graph/edges/{id}—
rest.edge.list()GET/graphspaces/{graphspace}/graphs/{graph}/graph/edgesvertex_id, direction, label, properties, keep_start_p, offset, page, limit
rest.edge.update_batch()PUT/graphspaces/{graphspace}/graphs/{graph}/graph/edges/batch—
rest.edge.update_by_id()PUT/graphspaces/{graphspace}/graphs/{graph}/graph/edges/{id}action
rest.edge_existence.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/edgeexistsource, target, label, sort_values, limit
rest.edge_label.create()POST/graphspaces/{graphspace}/graphs/{graph}/schema/edgelabels—
rest.edge_label.delete()DELETE/graphspaces/{graphspace}/graphs/{graph}/schema/edgelabels/{name}—
rest.edge_label.get()GET/graphspaces/{graphspace}/graphs/{graph}/schema/edgelabels/{name}—
rest.edge_label.list()GET/graphspaces/{graphspace}/graphs/{graph}/schema/edgelabelsnames
rest.edge_label.update()PUT/graphspaces/{graphspace}/graphs/{graph}/schema/edgelabels/{name}action
rest.edges.list()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/edgesids
rest.edges.scan()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/edges/scanstart, end, page, page_limit
rest.edges.shards()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/edges/shardssplit_size
rest.exception_trace.get()GET/exception/trace—
rest.exception_trace.trace()PUT/exception/trace—
rest.fusiform_similarity.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/fusiformsimilarity—
rest.graph_space.check_default_role()GET/graphspaces/{graphspace}/roleuser, role, graph
rest.graph_space.create()POST/graphspaces—
rest.graph_space.delete()DELETE/graphspaces/{name}—
rest.graph_space.delete_default_role()DELETE/graphspaces/{graphspace}/roleuser, role, graph
rest.graph_space.get()GET/graphspaces/{graphspace}—
rest.graph_space.list()GET/graphspaces—
rest.graph_space.list_profile()GET/graphspaces/profileprefix
rest.graph_space.manage()PUT/graphspaces/{name}—
rest.graph_space.set_default_role()POST/graphspaces/{graphspace}/role—
rest.graph_space_group.create()POST/graphspaces/{graphspace}/auth/groups—
rest.graph_space_group.delete()DELETE/graphspaces/{graphspace}/auth/groups/{id}—
rest.graph_space_group.get()GET/graphspaces/{graphspace}/auth/groups/{id}—
rest.graph_space_group.list()GET/graphspaces/{graphspace}/auth/groupslimit
rest.graph_space_group.update()PUT/graphspaces/{graphspace}/auth/groups/{id}—
rest.graphs.clear()DELETE/graphspaces/{graphspace}/graphs/{name}/clearconfirm_message
rest.graphs.clone_schema()POST/graphspaces/{graphspace}/graphs/{name}/schema-clonesource
rest.graphs.compact()PUT/graphspaces/{graphspace}/graphs/{name}/compact—
rest.graphs.create()POST/graphspaces/{graphspace}/graphs/{name}clone_graph_name
rest.graphs.create_by_text()POST/graphspaces/{graphspace}/graphs/{name}clone_graph_name
rest.graphs.create_snapshot()PUT/graphspaces/{graphspace}/graphs/{name}/snapshot_create—
rest.graphs.drop()DELETE/graphspaces/{graphspace}/graphs/{name}confirm_message
rest.graphs.get()GET/graphspaces/{graphspace}/graphs/{name}—
rest.graphs.get_conf()GET/graphspaces/{graphspace}/graphs/{name}/conf—
rest.graphs.get_default()GET/graphspaces/{graphspace}/graphs/default—
rest.graphs.graph_read_mode_get()GET/graphspaces/{graphspace}/graphs/{name}/graph_read_mode—
rest.graphs.graph_read_mode_set()PUT/graphspaces/{graphspace}/graphs/{name}/graph_read_mode—
rest.graphs.list()GET/graphspaces/{graphspace}/graphs—
rest.graphs.list_profile()GET/graphspaces/{graphspace}/graphs/profileprefix
rest.graphs.loading_mode_get()GET/graphspaces/{graphspace}/graphs/{name}/mode/owners—
rest.graphs.loading_mode_set()PUT/graphspaces/{graphspace}/graphs/{name}/mode/owners—
rest.graphs.manage()PUT/graphspaces/{graphspace}/graphs/{name}—
rest.graphs.mode_get()GET/graphspaces/{graphspace}/graphs/{name}/mode—
rest.graphs.mode_set()PUT/graphspaces/{graphspace}/graphs/{name}/mode—
rest.graphs.reload()PUT/graphspaces/{graphspace}/graphs/manage—
rest.graphs.resume_snapshot()PUT/graphspaces/{graphspace}/graphs/{name}/snapshot_resume—
rest.graphs.set_default()POST/graphspaces/{graphspace}/graphs/{name}/default—
rest.graphs.unset_default()DELETE/graphspaces/{graphspace}/graphs/{name}/default—
rest.gremlin.get()GET/gremlingremlin, language; additional query map
rest.gremlin.post()POST/gremlin—
rest.gremlin_job.post()POST/graphspaces/{graphspace}/graphs/{graph}/jobs/gremlin—
rest.group.create()POST/auth/groups—
rest.group.delete()DELETE/auth/groups/{id}—
rest.group.get()GET/auth/groups/{id}—
rest.group.list()GET/auth/groupslimit
rest.group.update()PUT/auth/groups/{id}—
rest.index_label.create()POST/graphspaces/{graphspace}/graphs/{graph}/schema/indexlabels—
rest.index_label.delete()DELETE/graphspaces/{graphspace}/graphs/{graph}/schema/indexlabels/{name}—
rest.index_label.get()GET/graphspaces/{graphspace}/graphs/{graph}/schema/indexlabels/{name}—
rest.index_label.list()GET/graphspaces/{graphspace}/graphs/{graph}/schema/indexlabelsnames
rest.index_label.update()PUT/graphspaces/{graphspace}/graphs/{graph}/schema/indexlabels/{name}action
rest.jaccard_similarity.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/jaccardsimilarityvertex, other, direction, label, max_degree
rest.jaccard_similarity.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/jaccardsimilarity—
rest.kneighbor.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/kneighborsource, direction, label, max_depth, count_only, max_degree, limit
rest.kneighbor.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/kneighbor—
rest.kout.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/koutsource, direction, label, max_depth, nearest, count_only, max_degree, capacity, limit
rest.kout.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/kout—
rest.login.login()POST/auth/login—
rest.login.logout()DELETE/auth/logout—
rest.login.verify_token()GET/auth/verify—
rest.manager.check_default_role()GET/graphspaces/{graphspace}/auth/managers/defaultrole, graph
rest.manager.check_role()GET/graphspaces/{graphspace}/auth/managers/checktype
rest.manager.create_manager()POST/graphspaces/{graphspace}/auth/managers—
rest.manager.delete()DELETE/graphspaces/{graphspace}/auth/managersuser, type
rest.manager.get_roles_in_gs()GET/graphspaces/{graphspace}/auth/managers/roleuser
rest.manager.list()GET/graphspaces/{graphspace}/auth/managerstype
rest.metrics.all()GET/metricstype
rest.metrics.backend()GET/metrics/backend—
rest.metrics.counters()GET/metrics/counters—
rest.metrics.gauges()GET/metrics/gauges—
rest.metrics.histograms()GET/metrics/histograms—
rest.metrics.meters()GET/metrics/meters—
rest.metrics.statistics()GET/metrics/statisticstype
rest.metrics.system()GET/metrics/system—
rest.metrics.timers()GET/metrics/timers—
rest.multi_node_shortest_path.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/multinodeshortestpath—
rest.neighbor_rank.neighbor_rank()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/neighborrank—
rest.paths.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/pathssource, target, direction, label, max_depth, max_degree, capacity, limit
rest.paths.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/paths—
rest.personal_rank.personal_rank()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/personalrank—
rest.profile.get_profile()GET/—
rest.profile.show_all_apis()GET/apis—
rest.project.create()POST/graphspaces/{graphspace}/auth/projects—
rest.project.delete()DELETE/graphspaces/{graphspace}/auth/projects/{id}—
rest.project.get()GET/graphspaces/{graphspace}/auth/projects/{id}—
rest.project.list()GET/graphspaces/{graphspace}/auth/projectslimit
rest.project.update()PUT/graphspaces/{graphspace}/auth/projects/{id}action
rest.property_key.create()POST/graphspaces/{graphspace}/graphs/{graph}/schema/propertykeys—
rest.property_key.delete()DELETE/graphspaces/{graphspace}/graphs/{graph}/schema/propertykeys/{name}—
rest.property_key.get()GET/graphspaces/{graphspace}/graphs/{graph}/schema/propertykeys/{name}—
rest.property_key.list()GET/graphspaces/{graphspace}/graphs/{graph}/schema/propertykeysnames
rest.property_key.update()PUT/graphspaces/{graphspace}/graphs/{graph}/schema/propertykeys/{name}action
rest.raft.add_peer()POST/graphspaces/{graphspace}/graphs/{graph}/raft/add_peergroup, endpoint
rest.raft.get_leader()GET/graphspaces/{graphspace}/graphs/{graph}/raft/get_leadergroup
rest.raft.list_peers()GET/graphspaces/{graphspace}/graphs/{graph}/raft/list_peersgroup
rest.raft.remove_peer()POST/graphspaces/{graphspace}/graphs/{graph}/raft/remove_peergroup, endpoint
rest.raft.set_leader()POST/graphspaces/{graphspace}/graphs/{graph}/raft/set_leadergroup, endpoint
rest.raft.transfer_leader()POST/graphspaces/{graphspace}/graphs/{graph}/raft/transfer_leadergroup, endpoint
rest.rays.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/rayssource, direction, label, max_depth, max_degree, capacity, limit, with_vertex, with_edge
rest.rebuild.edge_label_rebuild()PUT/graphspaces/{graphspace}/graphs/{graph}/jobs/rebuild/edgelabels/{name}—
rest.rebuild.index_label_rebuild()PUT/graphspaces/{graphspace}/graphs/{graph}/jobs/rebuild/indexlabels/{name}—
rest.rebuild.vertex_label_rebuild()PUT/graphspaces/{graphspace}/graphs/{graph}/jobs/rebuild/vertexlabels/{name}—
rest.resource_allocation.create()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/resourceallocationvertex, other, direction, label, max_degree, limit
rest.rings.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/ringssource, direction, label, max_depth, source_in_ring, max_degree, capacity, limit, with_vertex, with_edge
rest.same_neighbors.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/sameneighborsvertex, other, direction, label, max_degree, limit
rest.same_neighbors.same_neighbors()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/sameneighbors—
rest.same_neighbors_batch.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/sameneighborsbatch—
rest.schema.list()GET/graphspaces/{graphspace}/graphs/{graph}/schema—
rest.schema_template.create()POST/graphspaces/{graphspace}/schematemplates—
rest.schema_template.delete()DELETE/graphspaces/{graphspace}/schematemplates/{name}—
rest.schema_template.get()GET/graphspaces/{graphspace}/schematemplates/{name}—
rest.schema_template.list()GET/graphspaces/{graphspace}/schematemplates—
rest.schema_template.update()PUT/graphspaces/{graphspace}/schematemplates/{name}—
rest.shortest_path.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/shortestpathsource, target, direction, label, max_depth, max_degree, skip_degree, with_vertex, with_edge, capacity
rest.single_source_shortest_path.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/singlesourceshortestpathsource, direction, label, weight, max_degree, skip_degree, with_vertex, with_edge, capacity, limit
rest.target.create()POST/graphspaces/{graphspace}/auth/targets—
rest.target.delete()DELETE/graphspaces/{graphspace}/auth/targets/{id}—
rest.target.get()GET/graphspaces/{graphspace}/auth/targets/{id}—
rest.target.list()GET/graphspaces/{graphspace}/auth/targetslimit
rest.target.update()PUT/graphspaces/{graphspace}/auth/targets/{id}—
rest.task.delete()DELETE/graphspaces/{graphspace}/graphs/{graph}/tasks/{id}force
rest.task.get()GET/graphspaces/{graphspace}/graphs/{graph}/tasks/{id}with_result
rest.task.list()GET/graphspaces/{graphspace}/graphs/{graph}/tasksstatus, ids, limit, page
rest.task.update()PUT/graphspaces/{graphspace}/graphs/{graph}/tasks/{id}action
rest.template_paths.post()POST/graphspaces/{graphspace}/graphs/{graph}/traversers/templatepaths—
rest.user.create()POST/graphspaces/{graphspace}/auth/users—
rest.user.delete()DELETE/graphspaces/{graphspace}/auth/users/{id}—
rest.user.get()GET/graphspaces/{graphspace}/auth/users/{id}—
rest.user.list()GET/graphspaces/{graphspace}/auth/usersname, limit
rest.user.role()GET/graphspaces/{graphspace}/auth/users/{id}/role—
rest.user.update()PUT/graphspaces/{graphspace}/auth/users/{id}—
rest.variables.delete()DELETE/graphspaces/{graphspace}/graphs/{graph}/variables/{key}—
rest.variables.get()GET/graphspaces/{graphspace}/graphs/{graph}/variables/{key}—
rest.variables.list()GET/graphspaces/{graphspace}/graphs/{graph}/variables—
rest.variables.update()PUT/graphspaces/{graphspace}/graphs/{graph}/variables/{key}—
rest.version.list()GET/versions—
rest.vertex.create()POST/graphspaces/{graphspace}/graphs/{graph}/graph/vertices—
rest.vertex.create_batch()POST/graphspaces/{graphspace}/graphs/{graph}/graph/vertices/batch—
rest.vertex.delete()DELETE/graphspaces/{graphspace}/graphs/{graph}/graph/vertices/{id}label
rest.vertex.get()GET/graphspaces/{graphspace}/graphs/{graph}/graph/vertices/{id}—
rest.vertex.list()GET/graphspaces/{graphspace}/graphs/{graph}/graph/verticeslabel, properties, keep_start_p, offset, page, limit
rest.vertex.update_batch()PUT/graphspaces/{graphspace}/graphs/{graph}/graph/vertices/batch—
rest.vertex.update_by_id()PUT/graphspaces/{graphspace}/graphs/{graph}/graph/vertices/{id}action
rest.vertex_label.create()POST/graphspaces/{graphspace}/graphs/{graph}/schema/vertexlabels—
rest.vertex_label.delete()DELETE/graphspaces/{graphspace}/graphs/{graph}/schema/vertexlabels/{name}—
rest.vertex_label.get()GET/graphspaces/{graphspace}/graphs/{graph}/schema/vertexlabels/{name}—
rest.vertex_label.list()GET/graphspaces/{graphspace}/graphs/{graph}/schema/vertexlabelsnames
rest.vertex_label.update()PUT/graphspaces/{graphspace}/graphs/{graph}/schema/vertexlabels/{name}action
rest.vertices.list()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/verticesids
rest.vertices.scan()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/vertices/scanstart, end, page, page_limit
rest.vertices.shards()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/vertices/shardssplit_size
rest.weighted_shortest_path.get()GET/graphspaces/{graphspace}/graphs/{graph}/traversers/weightedshortestpathsource, target, direction, label, weight, max_degree, skip_degree, with_vertex, with_edge, capacity
rest.white_ip_list.list()GET/whiteiplist—
rest.white_ip_list.update_status()PUT/whiteipliststatus
rest.white_ip_list.update_white_ips()POST/whiteiplist—

异常处理

常见异常定义位于 pyhugegraph.utils.exceptions:

异常类型触发场景
NotAuthorizedError服务端返回 HTTP 401 未认证
NotFoundError服务端返回 HTTP 404 资源未找到
ServerError服务端返回非 2xx 响应(附带服务端错误详情)
ResponseParseError响应内容无法反序列化为预期格式
ServiceUnavailableError服务端暂时不可用
InvalidParameterError, CreateError, RemoveError, UpdateError, DataFormatError客户端本地参数或格式校验失败

敏感参数(密码、Token、密钥等)在日志输出中会自动脱敏处理。

1from pyhugegraph.utils.exceptions import NotFoundError
2
3try:
4    graph.get_vertex_by_id("missing-id")
5except NotFoundError:
6    print("未找到指定顶点")

开发与测试验证

在 HugeGraph-AI 仓库根目录下执行代码规范与测试套件:

  1. 代码格式化与静态检查:

    1uv run --extra dev ruff format --check .
    2uv run --extra dev ruff check .
    3uv run --extra dev ty check hugegraph-python-client/src/pyhugegraph
  2. 运行单元测试与契约测试:

    1uv run pytest hugegraph-python-client/src/tests -m "unit or contract"
  3. 针对正在运行的 HugeGraph Server 执行集成测试:

    1HUGEGRAPH_URL=http://127.0.0.1:8080 \
    2HUGEGRAPH_GRAPH=hugegraph \
    3HUGEGRAPH_USER=admin \
    4HUGEGRAPH_PASSWORD=admin \
    5uv run pytest hugegraph-python-client/src/tests -m "integration and hugegraph"

主线 CI 默认使用 hugegraph/hugegraph:latest 镜像进行集成验证,并对 1.7.0 执行兼容回归。源码与测试位于 hugegraph-python-client/src/pyhugegraph/ 和 hugegraph-python-client/src/tests/。

3 - HugeGraph Go 客户端快速入门

HugeGraph Go Client 是 Toolchain 仓库中的 Go SDK,目前提供版本查询、Schema(PropertyKey、VertexLabel、EdgeLabel)、顶点和 Gremlin API。边数据 API 尚未实现。

该模块仍在开发中。接口范围以 hugegraph-client-go/api/v1 下的源码为准。

环境要求

  • Go 1.19 或更高版本
  • 可访问的 HugeGraph Server,默认示例地址为 http://127.0.0.1:8080

安装

在 Go module 项目中执行:

1go get github.com/apache/hugegraph-toolchain/hugegraph-client-go

初始化客户端

NewCommonClient 要求 Host 是 IP 地址,Port 在 1 到 65535 之间;客户端始终使用明文 HTTP 连接。未启用认证时,用户名和密码留空;只有两者都设置时才会发送 Basic Auth。

GraphSpace 非空时,Vertex 和 Schema API(Schema()、Propertykey、VertexLabel、EdgeLabel)使用 /graphspaces/{space}/graphs/{graph}/... 路径;留空时使用旧版 /graphs/{graph}/... 路径。默认图空间填写 DEFAULT。 Gremlin 默认 aliases 也使用 GraphSpace,空值按 DEFAULT 处理。Version() 始终请求 /versions,不依赖图空间。

 1package main
 2
 3import (
 4	"fmt"
 5	"log"
 6
 7	hugegraph "github.com/apache/hugegraph-toolchain/hugegraph-client-go"
 8)
 9
10func main() {
11	client, err := hugegraph.NewCommonClient(hugegraph.Config{
12		Host:       "127.0.0.1",
13		Port:       8080,
14		GraphSpace: "DEFAULT",
15		Graph:      "hugegraph",
16		Username:   "",
17		Password:   "",
18	})
19	if err != nil {
20		log.Fatal(err)
21	}
22
23	response, err := client.Version()
24	if err != nil {
25		log.Fatal(err)
26	}
27	defer response.Body.Close()
28
29	fmt.Println(response.Versions.Version)
30}

Version() 返回的 Versions 包含 HugeGraph Server、Core、Gremlin 和 REST API 版本。若使用源码提供的 NewDefaultCommonClient(),默认连接 127.0.0.1:8080 下的 hugegraph 图,使用 admin/pa 认证,并挂载一个打印全部请求和响应体的 ColorLogger;生产代码通常应显式传入配置。

配置项

hugegraph.Config 包含以下字段:

字段类型说明
HoststringHugeGraph Server 的 IP 地址,不支持主机名
PortintHugeGraph Server 的 REST 端口,取值 1 到 65535
GraphSpacestringVertex、Schema API 和 Gremlin 默认 aliases 使用的图空间;默认空间填写 DEFAULT
GraphstringServer 上配置的图名
UsernamestringServer 用户名,未启用认证时填空字符串
PasswordstringServer 密码,未启用认证时填空字符串
Transporthttp.RoundTripper自定义 HTTP transport,为 nil 时使用 http.DefaultTransport
Loggerhgtransport.Logger请求/响应日志,为 nil 时不记录日志

hgtransport 包提供四种 logger:TextLogger(纯文本)、ColorLogger(终端彩色)、CurlLogger(可执行的 curl 命令)和 JSONLogger(JSON 行)。它们的字段相同:Output(io.Writer)、EnableRequestBody 和 EnableResponseBody。

 1import (
 2	"os"
 3
 4	hugegraph "github.com/apache/hugegraph-toolchain/hugegraph-client-go"
 5	"github.com/apache/hugegraph-toolchain/hugegraph-client-go/hgtransport"
 6)
 7
 8client, err := hugegraph.NewCommonClient(hugegraph.Config{
 9	Host:  "127.0.0.1",
10	Port:  8080,
11	Graph: "hugegraph",
12	Logger: &hgtransport.ColorLogger{
13		Output:             os.Stdout,
14		EnableRequestBody:  true,
15		EnableResponseBody: true,
16	},
17})

已实现的入口

CommonClient 当前公开以下入口:

入口用途
Version()查询服务端版本
Schema()查询完整 Schema
PropertykeyCreate、GetAll、GetByName、UpdateUserdata、DeleteByName
VertexLabelCreate、GetAll、GetByName、UpdateUserdata、DeleteByName
EdgeLabelCreate、GetAll、DeleteByName
VertexCreate、BatchCreate、UpdateProperties(通过 WithAction 指定 append 或 eliminate)
GremlinGet 和 Post。Post 默认 language 为 gremlin-groovy,根据 GraphSpace 和 Graph 自动填充 graph/g aliases,并在 Data 中返回解析后的结果;Get 只返回状态码,并把原始响应打印到 stdout。

每个操作都通过挂在操作本身上的 With... 函数式选项传参,例如 client.Gremlin.Post.WithGremlin(...) 或 client.Propertykey.GetByName.WithName(...)。

EdgeLabel.Create 的请求数据允许 Properties: nil 或空切片 []string{},用于创建无属性的边标签。

类型化 API 返回的 err 表示参数校验、传输、响应读取或 JSON 解码错误。 HTTP 4xx/5xx 仍可能返回 err == nil,例如创建顶点时指定不存在的 label 会返回 HTTP 400。 读取结果数据前,请检查 response.StatusCode 是否属于 2xx。调用 Gremlin.Post 时,还需检查 response.Data.Status.Code 是否为成功的 Gremlin 协议状态码(2xx)。

 1resp, err := client.Gremlin.Post(
 2	client.Gremlin.Post.WithGremlin("g.V().limit(3)"),
 3)
 4if err != nil {
 5	log.Fatal(err)
 6}
 7defer resp.Body.Close()
 8if resp.StatusCode < 200 || resp.StatusCode >= 300 {
 9	log.Fatalf("HugeGraph returned HTTP %d", resp.StatusCode)
10}
11if resp.Data.Status.Code < 200 || resp.Data.Status.Code >= 300 {
12	log.Fatalf("Gremlin returned status %d: %s", resp.Data.Status.Code, resp.Data.Status.Message)
13}
14fmt.Println(resp.Data.Result.Data)

Vertex 相关操作的入参是 internal/model 包中的 model.Vertex[any]。Go 不允许从其他 module 导入 internal 包,因此目前 Vertex API 只能在客户端 module 内部调用;其测试文件也已全部注释。

完整调用方式可参考各 API 目录中的测试,例如 version_test.go、gemlin_test.go 和 vertexlabel_test.go。