From ee999a544e08930ed481b7c4ddd86635c192cc2c Mon Sep 17 00:00:00 2001 From: n24q02m Date: Thu, 24 Sep 2026 21:13:29 +0700 Subject: [PATCH 01/17] docs: add Cypher query language guide (EN/CN) and register in nav - Document the Cypher API (REST endpoint, Java client), MATCH/WHERE/RETURN, CREATE/SET/DELETE, aggregation, and Gremlin equivalents for unsupported constructs - State known limitations honestly: no parameterized queries, partial clause coverage via the cypher-for-gremlin transpiler, no CALL procedures, single statement per request - Update language section indexes (EN/CN) to cover both languages - Register the page in data/docs_nav.json (group tree, section tree, active_path breadcrumb, section children) and data/version_routes.json (latest only; page does not exist in 1.0-1.7) - Closes apache/hugegraph-doc cypher doc gap tracked in apache/hugegraph#2205 --- content/cn/docs/language/_index.md | 2 +- content/cn/docs/language/hugegraph-cypher.md | 135 +++++++++++++++++++ content/en/docs/language/_index.md | 2 +- content/en/docs/language/hugegraph-cypher.md | 135 +++++++++++++++++++ data/docs_nav.json | 16 ++- data/version_routes.json | 14 ++ 6 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 content/cn/docs/language/hugegraph-cypher.md create mode 100644 content/en/docs/language/hugegraph-cypher.md diff --git a/content/cn/docs/language/_index.md b/content/cn/docs/language/_index.md index 16dc29be79..46307b379d 100644 --- a/content/cn/docs/language/_index.md +++ b/content/cn/docs/language/_index.md @@ -4,4 +4,4 @@ linkTitle: "查询语言" weight: 7 --- -HugeGraph 支持 Gremlin 和 Cypher。这里主要介绍 Gremlin 用法;Cypher HTTP 接口见 [Cypher API](/cn/docs/clients/restful-api/cypher/)。 +HugeGraph 支持 Gremlin 和 Cypher。本节涵盖两种语言;Cypher HTTP 接口见 [Cypher API](/cn/docs/clients/restful-api/cypher/)。 diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md new file mode 100644 index 0000000000..a27caa89c3 --- /dev/null +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -0,0 +1,135 @@ +--- +title: "HugeGraph Cypher" +linkTitle: "Cypher 查询语言" +weight: 2 +--- + +### 概述 + +HugeGraph 支持 [Cypher](https://opencypher.org/) —— 最初由 Neo4j 创建、并由 [openCypher](https://github.com/opencypher/openCypher) 标准化的声明式图查询语言。Gremlin 是命令式的遍历语言,而 Cypher 只需描述想要的图模式(`MATCH`、`WHERE`、`RETURN`),由引擎决定如何执行。 + +HugeGraph 通过 [cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) 转译器将 Cypher 语句翻译为 Gremlin,再在 TinkerPop 技术栈上执行。因此 HugeGraph 的 Cypher 能力覆盖转译器所实现的 openCypher 9 语法面 —— 详见下文[已知限制](#已知限制)。 + +### 何时用 Cypher、何时用 Gremlin + +| 适合用 Cypher | 适合用 Gremlin | +|---|---| +| 正在从 Neo4j 迁移,或已熟悉 Cypher | 需要 HugeGraph 的完整功能面 | +| 需要声明式模式匹配(`MATCH (a)-[:KNOWS]->(b)`) | 需要精细的遍历控制、自定义步骤或 lambda | +| 查询以读模式和投影为主 | 需要图算法、OLAP 或 Cypher 未暴露的功能 | + +凡是 Cypher 表达不了的,等价的 Gremlin 查询总是可用 —— 下文示例同时给出两种写法。 + +### 调用 Cypher API + +Cypher 语句通过 HugeGraph Server 的 REST 端点提交: + +```http +GET /graphspaces/{graphspace}/graphs/{graph}/cypher?cypher={statement} +POST /graphspaces/{graphspace}/graphs/{graph}/cypher +``` + +该端点始终要求 `Authorization` 头(`Basic` 或 `Bearer`),即使服务端未开启认证 —— 凭据会被转发给 Gremlin Server。完整的请求/响应格式见 [Cypher REST API 参考](/cn/docs/clients/restful-api/cypher/)。 + +示例: + +```bash +curl -H "Authorization: Bearer $TOKEN" \ + "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/cypher?cypher=MATCH%20(n:person)%20RETURN%20n.name%20LIMIT%2010" +``` + +Java 客户端使用 `CypherManager`(见 [hugegraph-client](/cn/docs/clients/hugegraph-client/)): + +```java +ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.name LIMIT 10"); +``` + +### 基础示例 + +以下示例假设图中存在 `person` 顶点(`name`、`age`、`city` 属性)和 `knows` 边。 + +#### 查询 — MATCH / WHERE / RETURN + +```cypher +// 所有名为 "marko" 的 person +MATCH (n:person) WHERE n.name = 'marko' RETURN n + +// 投影 + 排序 + 限制条数 +MATCH (n:person) +WHERE n.age > 30 +RETURN n.name AS name, n.age AS age +ORDER BY age DESC +LIMIT 10 + +// 关系模式 +MATCH (a:person)-[:knows]->(b:person) +WHERE a.name = 'marko' +RETURN b.name AS friend +``` + +#### 创建 — CREATE + +```cypher +// 创建顶点 +CREATE (n:person {name: 'josh', age: 32, city: 'beijing'}) + +// 创建两个顶点及它们之间的边 +CREATE (a:person {name: 'peter'})-[:knows]->(b:person {name: 'lop'}) +``` + +#### 更新 — SET / REMOVE + +```cypher +MATCH (n:person) WHERE n.name = 'josh' +SET n.age = 33 +REMOVE n.city +``` + +#### 删除 — DELETE / DETACH DELETE + +```cypher +// 删除边 +MATCH (a:person)-[r:knows]->(b:person) +WHERE a.name = 'peter' AND b.name = 'lop' +DELETE r + +// 删除顶点及其所有边 +MATCH (n:person) WHERE n.name = 'josh' +DETACH DELETE n +``` + +#### 聚合 + +```cypher +MATCH (n:person) RETURN count(n) AS total +MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC +``` + +### 等价的 Gremlin 写法 + +每条 Cypher 语句在内部都会被翻译为 Gremlin。当某个 Cypher 特性不受支持时,可直接编写遍历: + +| Cypher | 等价 Gremlin | +|---|---| +| `MATCH (n:person) WHERE n.name='marko' RETURN n` | `g.V().hasLabel('person').has('name','marko')` | +| `MATCH (a)-[:knows]->(b) RETURN b` | `g.V().out('knows')` | +| `CREATE (n:person {name:'x'})` | `g.addV('person').property('name','x')` | +| `MATCH (n) DETACH DELETE n` | `g.V().drop()` | +| `MATCH (n:person) RETURN count(n)` | `g.V().hasLabel('person').count()` | + +### 已知限制 + +HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代的工具链。已知缺口: + +- **不支持参数化查询** —— API 只接受原始语句字符串,不支持 `$param` 占位符。请在客户端先对值做转义/净化再拼接到语句中。 +- **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 `MERGE ... ON CREATE SET`、map projection、某些 `WHERE` 谓词形式如 `NOT ... IN`,以及部分 `datetime()`/正则函数)。不支持的结构会在翻译阶段报错。 +- **不支持 `CALL` 过程** —— HugeGraph 的图算法(最短路径、k-out、personalrank 等)未暴露为 Cypher 过程;请改用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin。 +- **每次请求仅一条语句** —— 不支持多语句脚本,请每次调用发送一条语句。 + +当语句翻译失败时,响应的 `status.message` 会包含转译器错误信息。遇到缺口时,等价的 Gremlin 写法是受支持的回退方案。 + +### 延伸阅读 + +- [Cypher REST API 参考](/cn/docs/clients/restful-api/cypher/) +- [Gremlin 查询语言](/cn/docs/language/hugegraph-gremlin/) +- [openCypher 项目](https://opencypher.org/) —— 语言规范与资源 diff --git a/content/en/docs/language/_index.md b/content/en/docs/language/_index.md index 7362b4f706..c4f38a9572 100644 --- a/content/en/docs/language/_index.md +++ b/content/en/docs/language/_index.md @@ -4,4 +4,4 @@ linkTitle: "Query Languages" weight: 7 --- -HugeGraph supports Gremlin and Cypher. This section mainly covers Gremlin; see the [Cypher API](/docs/clients/restful-api/cypher/) for the Cypher HTTP interface. +HugeGraph supports Gremlin and Cypher. This section covers both languages; see the [Cypher API](/docs/clients/restful-api/cypher/) for the Cypher HTTP interface. diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md new file mode 100644 index 0000000000..8ed88a08c1 --- /dev/null +++ b/content/en/docs/language/hugegraph-cypher.md @@ -0,0 +1,135 @@ +--- +title: "HugeGraph Cypher" +linkTitle: "Cypher Query Language" +weight: 2 +--- + +### Overview + +HugeGraph supports [Cypher](https://opencypher.org/), the declarative graph query language originally created by Neo4j and standardized as [openCypher](https://github.com/opencypher/openCypher). While Gremlin is an imperative traversal language, Cypher lets you describe the graph pattern you want (`MATCH`, `WHERE`, `RETURN`) and lets the engine decide how to execute it. + +HugeGraph executes Cypher by translating the statement to Gremlin through the [cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) transpiler, then running the resulting traversal on the TinkerPop stack. This means Cypher support in HugeGraph covers the openCypher 9 surface that the transpiler implements — see [Known limitations](#known-limitations) below. + +### When to use Cypher vs Gremlin + +| Use Cypher when | Use Gremlin when | +|---|---| +| You are migrating from Neo4j or already know Cypher | You need the full HugeGraph feature surface | +| You want declarative pattern matching (`MATCH (a)-[:KNOWS]->(b)`) | You need fine-grained traversal control, custom steps, or lambdas | +| Your queries are read-mostly patterns and projections | You need graph algorithms, OLAP, or features Cypher does not expose | + +For anything Cypher cannot express, the equivalent Gremlin query always works — examples below show both. + +### Calling the Cypher API + +Cypher statements are submitted to the HugeGraph Server through the REST endpoint: + +```http +GET /graphspaces/{graphspace}/graphs/{graph}/cypher?cypher={statement} +POST /graphspaces/{graphspace}/graphs/{graph}/cypher +``` + +The endpoint always requires an `Authorization` header (`Basic` or `Bearer`), even when server authentication is disabled — the credentials are forwarded to the Gremlin Server. See the [Cypher REST API reference](/docs/clients/restful-api/cypher/) for the full request/response format. + +Example: + +```bash +curl -H "Authorization: Bearer $TOKEN" \ + "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/cypher?cypher=MATCH%20(n:person)%20RETURN%20n.name%20LIMIT%2010" +``` + +From the Java client, use `CypherManager` (see [hugegraph-client](/docs/clients/hugegraph-client/)): + +```java +ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.name LIMIT 10"); +``` + +### Basic examples + +The examples below assume a graph with `person` vertices (`name`, `age`, `city` properties) and `knows` edges. + +#### Read — MATCH / WHERE / RETURN + +```cypher +// All persons named "marko" +MATCH (n:person) WHERE n.name = 'marko' RETURN n + +// Projection with ordering and limit +MATCH (n:person) +WHERE n.age > 30 +RETURN n.name AS name, n.age AS age +ORDER BY age DESC +LIMIT 10 + +// Relationship pattern +MATCH (a:person)-[:knows]->(b:person) +WHERE a.name = 'marko' +RETURN b.name AS friend +``` + +#### Create — CREATE + +```cypher +// Create a vertex +CREATE (n:person {name: 'josh', age: 32, city: 'beijing'}) + +// Create two vertices and an edge between them +CREATE (a:person {name: 'peter'})-[:knows]->(b:person {name: 'lop'}) +``` + +#### Update — SET / REMOVE + +```cypher +MATCH (n:person) WHERE n.name = 'josh' +SET n.age = 33 +REMOVE n.city +``` + +#### Delete — DELETE / DETACH DELETE + +```cypher +// Delete an edge +MATCH (a:person)-[r:knows]->(b:person) +WHERE a.name = 'peter' AND b.name = 'lop' +DELETE r + +// Delete a vertex and all its edges +MATCH (n:person) WHERE n.name = 'josh' +DETACH DELETE n +``` + +#### Aggregation + +```cypher +MATCH (n:person) RETURN count(n) AS total +MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC +``` + +### Gremlin equivalents + +Every Cypher statement is translated to Gremlin internally. When a Cypher feature is unsupported, write the traversal directly: + +| Cypher | Gremlin equivalent | +|---|---| +| `MATCH (n:person) WHERE n.name='marko' RETURN n` | `g.V().hasLabel('person').has('name','marko')` | +| `MATCH (a)-[:knows]->(b) RETURN b` | `g.V().out('knows')` | +| `CREATE (n:person {name:'x'})` | `g.addV('person').property('name','x')` | +| `MATCH (n) DETACH DELETE n` | `g.V().drop()` | +| `MATCH (n:person) RETURN count(n)` | `g.V().hasLabel('person').count()` | + +### Known limitations + +Cypher support in HugeGraph is bounded by the transpiler layer, which is based on openCypher 9 era tooling. Known gaps: + +- **No parameterized queries** — the API accepts a raw statement string only; `$param` placeholders are not supported. Sanitize/escape values on the client side before interpolating them into the statement. +- **Partial clause coverage** — some openCypher constructs are not translated (for example `MERGE ... ON CREATE SET`, map projections, some `WHERE` predicate forms such as `NOT ... IN`, and certain `datetime()`/regex functions). Unsupported constructs fail at translation time with an error from the transpiler. +- **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. +- **Single statement per request** — multi-statement scripts are not supported; send one statement per call. + +When a statement fails translation, the response `status.message` contains the transpiler error. If you hit a gap, the Gremlin equivalent is the supported fallback. + +### Further reading + +- [Cypher REST API reference](/docs/clients/restful-api/cypher/) +- [Gremlin Query Language](/docs/language/hugegraph-gremlin/) +- [openCypher project](https://opencypher.org/) — language specification and resources diff --git a/data/docs_nav.json b/data/docs_nav.json index d5299c62d7..184bd5df63 100644 --- a/data/docs_nav.json +++ b/data/docs_nav.json @@ -215,6 +215,9 @@ "children": [ { "page": "/docs/language/hugegraph-gremlin" + }, + { + "page": "/docs/language/hugegraph-cypher" } ] }, @@ -666,6 +669,11 @@ "page": "/docs/language/hugegraph-gremlin", "url": "/docs/language/hugegraph-gremlin/", "children": [] + }, + { + "page": "/docs/language/hugegraph-cypher", + "url": "/docs/language/hugegraph-cypher/", + "children": [] } ] }, @@ -1321,6 +1329,11 @@ "/docs/cla/": [ "@group/reference", "/docs/cla/" + ], + "/docs/language/hugegraph-cypher/": [ + "@group/develop", + "/docs/language/", + "/docs/language/hugegraph-cypher/" ] }, "children_by_url": { @@ -1398,7 +1411,8 @@ "/docs/quickstart/client/hugegraph-client-go" ], "/docs/language/": [ - "/docs/language/hugegraph-gremlin" + "/docs/language/hugegraph-gremlin", + "/docs/language/hugegraph-cypher" ], "/docs/config/": [ "/docs/config/config-guide", diff --git a/data/version_routes.json b/data/version_routes.json index bd7e4351ef..3238ec3132 100644 --- a/data/version_routes.json +++ b/data/version_routes.json @@ -1498,6 +1498,20 @@ "1.5": null, "1.3": null, "1.0": null + }, + "cn:language/hugegraph-cypher": { + "latest": "cn/docs/language/hugegraph-cypher/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, + "en:language/hugegraph-cypher": { + "latest": "docs/language/hugegraph-cypher/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null } }, "equivalents": [ From 36eef7daf694628a75c5e50cc4845336b6d2603f Mon Sep 17 00:00:00 2001 From: n24q02m Date: Thu, 24 Sep 2026 21:57:23 +0700 Subject: [PATCH 02/17] docs: add Cypher compatibility matrix and Neo4j migration guide (EN/CN) - cypher-compatibility.md: feature matrix with explicit evidence tiers (documented examples / transpiler TCK self-report / API surface / untested), failure behaviour, and Gremlin workarounds - migrate-from-neo4j.md: what carries over, habits to change (strong schema, no Cypher DDL/params/CALL), suggested migration path - Register both pages in data/docs_nav.json and data/version_routes.json (latest only; pages do not exist in 1.0-1.7) - CN anchors verified against Hugo-slugified heading ids - Companion pages to the Cypher language guide; related to #2205 --- .../cn/docs/language/cypher-compatibility.md | 52 ++++++++++++++++ .../cn/docs/language/migrate-from-neo4j.md | 53 ++++++++++++++++ .../en/docs/language/cypher-compatibility.md | 59 ++++++++++++++++++ .../en/docs/language/migrate-from-neo4j.md | 60 +++++++++++++++++++ data/docs_nav.json | 30 +++++++++- data/version_routes.json | 28 +++++++++ 6 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 content/cn/docs/language/cypher-compatibility.md create mode 100644 content/cn/docs/language/migrate-from-neo4j.md create mode 100644 content/en/docs/language/cypher-compatibility.md create mode 100644 content/en/docs/language/migrate-from-neo4j.md diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md new file mode 100644 index 0000000000..cedd258d90 --- /dev/null +++ b/content/cn/docs/language/cypher-compatibility.md @@ -0,0 +1,52 @@ +--- +title: "Cypher 兼容性" +linkTitle: "Cypher 兼容性" +weight: 3 +--- + +### 本页范围 + +HugeGraph 通过 [`cypher-for-gremlin`](https://github.com/opencypher/cypher-for-gremlin) +转译器(`org.opencypher.gremlin:translation:1.0.4`,发布于 2019-11-05)把 Cypher +翻译成 Gremlin 执行。因此 HugeGraph 的 Cypher 覆盖面等于该转译器实现的 +openCypher 9 子集 —— 用法见 [HugeGraph Cypher](/cn/docs/language/hugegraph-cypher/), +简版限制见[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 + +转译器 1.0.4 自报的 conformance 数据为 **879 通过 / 79 失败(约 91.7%)**。 +下表按现有证据对特性分级;它不能替代对你的真实负载做测试。 + +### 特性矩阵 + +| openCypher 特性 | 状态 | 证据层级 | 说明 / Gremlin 替代 | +|---|---|---|---| +| `MATCH` + `WHERE` + `RETURN`(节点模式) | ✅ 可用 | 文档示例 | [语言指南](/cn/docs/language/hugegraph-cypher/) | +| 关系模式 `(a)-[:KNOWS]->(b)` | ✅ 可用 | 文档示例 | — | +| `ORDER BY` / `LIMIT` / `SKIP` | ✅ 可用 | 文档示例 | — | +| `CREATE` 点/边、`SET` / `REMOVE`、`DELETE` / `DETACH DELETE` | ✅ 可用 | 文档示例 | — | +| 聚合(`count`、`sum`、`min`、`max`、`avg`) | ✅ 可用 | 文档示例 | — | +| `MERGE`(基础) | ⚠️ 部分 | 转译器报告 | `MERGE ... ON CREATE SET` / `ON MATCH SET` 不支持 → 用 Gremlin 先查后建 | +| 变长路径 `(a)-[:KNOWS*1..3]->(b)` | ⚠️ 未验证 | — | 优先用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin `repeat()` | +| `OPTIONAL MATCH`、`WITH`、`UNWIND` | ⚠️ 未验证 | — | 使用前先测试;可回退 Gremlin | +| 字符串 / 数学函数 | ⚠️ 部分 | 转译器报告 | 只覆盖 openCypher 9 函数子集;不支持的在翻译期报错 | +| `date()` / `datetime()` 函数 | ❌ 不支持 | Issue 记录 | 在客户端算好时间戳后以字面量传入 | +| 正则 `=~` 与 `NOT (... IN ...)` | ❌ 不支持 | Issue 记录 | 客户端过滤,或用 Gremlin 谓词(`TextP.regex`) | +| Map projection `n { .name, .age }` | ❌ 不支持 | Issue 记录 | 返回节点本身或显式属性 | +| 查询参数(`$param`) | ❌ 不支持 | API 面(`CypherAPI` 只接受语句字符串) | 在客户端转义/校验后拼接字面量 | +| `CALL` 过程(图算法) | ❌ 不支持 | API 面 | 使用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin | +| 多语句脚本 | ❌ 不支持 | API 面 | 每次请求一条语句 | +| Cypher 里的 DDL(`CREATE INDEX`、约束) | ❌ 不支持 | 架构 | 通过 [schema REST API](/cn/docs/clients/restful-api/schema/) 建索引/约束 | +| `EXPLAIN` / `PROFILE` | ❌ 不支持 | API 面 | 在 Gremlin 遍历上使用 `profile()` | + +图例:✅ 已在文档路径验证 · ⚠️ 部分支持或未在 HugeGraph 验证 —— 先测试 · +❌ Cypher API 不可达。 + +### 失败行为 + +不支持的写法在翻译期报错,响应 `status.message` 携带转译器错误。无法表达的 +语句始终有等价 Gremlin 写法 —— 见 +[对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法)。 + +### 持续完善 + +随着 conformance 证据增加,本矩阵会持续更新。针对真实 HugeGraph 服务运行 +openCypher TCK 并公布通过/失败矩阵,是把 ⚠️ 行变成确定答案的既定后续工作。 diff --git a/content/cn/docs/language/migrate-from-neo4j.md b/content/cn/docs/language/migrate-from-neo4j.md new file mode 100644 index 0000000000..1dca483180 --- /dev/null +++ b/content/cn/docs/language/migrate-from-neo4j.md @@ -0,0 +1,53 @@ +--- +title: "从 Neo4j 迁移" +linkTitle: "从 Neo4j 迁移" +weight: 4 +--- + +### 本页面向谁 + +正在评估 HugeGraph 的 Neo4j 用户。HugeGraph 的 Cypher 覆盖面由 +[cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) 转译器决定, +与 Neo4j 并非 1:1 等价 —— 逐项差异见 +[Cypher 兼容性矩阵](/cn/docs/language/cypher-compatibility/), +用法见 [HugeGraph Cypher](/cn/docs/language/hugegraph-cypher/)。 + +### 可以直接带过来的部分 + +| Neo4j 概念 | HugeGraph 对应 | +|---|---| +| 属性图模型(节点/关系/属性) | 相同 —— 顶点标签 / 边标签 / 属性 | +| 基础 Cypher:`MATCH`/`WHERE`/`RETURN`/`CREATE`/`SET`/`DELETE` | 直接可用(REST `/cypher` 端点或 Java 客户端 `CypherManager`) | +| 简单聚合(`count`/`sum`/`min`/`max`/`avg`) | 直接可用 | +| 依赖图遍历的查询需求 | Gremlin 遍历或 [traverser REST API](/cn/docs/clients/restful-api/traverser/)(k-out、最短路、personalrank 等) | + +### 需要改变习惯的部分 + +| 在 Neo4j 里 | 在 HugeGraph 里 | +|---|---| +| `CREATE INDEX` / `CREATE CONSTRAINT` | 通过 [schema REST API](/cn/docs/clients/restful-api/schema/) 建索引/约束;Cypher 不承载 DDL | +| 隐式 schema(属性随意添加) | **强 schema**:先定义 VertexLabel/EdgeLabel/PropertyKey,再写数据 | +| 参数化查询 `$param` | 暂不支持 —— 在客户端转义/校验后拼接字面量 | +| `CALL dbms.*` / `CALL algo.*` 过程 | 对应功能分散在 [traverser](/cn/docs/clients/restful-api/traverser/)、[task](/cn/docs/clients/restful-api/task/) 等 REST API | +| 驱动:Neo4j Bolt driver | [hugegraph-client](/cn/docs/clients/hugegraph-client/)(`CypherManager`)或任意 HTTP 客户端 | +| 事务边界在 Cypher 语句内 | 每次请求一个语句;批量写入用 [Loader](/cn/docs/guides/toolchain/) 或 bulkport | + +### 建议的迁移路径 + +1. **盘点查询**:把应用里的 Cypher 按 + [兼容性矩阵](/cn/docs/language/cypher-compatibility/) 分成 + "直接可用 / 需改写为 Gremlin / 需换 REST API" 三类。 +2. **先建 schema**:用 schema API 建好 VertexLabel/EdgeLabel/PropertyKey 和索引 —— + HugeGraph 在写入前要求 schema 存在。 +3. **导入数据**:小数据集用 REST;大批量用 + [HugeGraph Loader](https://github.com/apache/hugegraph-toolchain/tree/master/hugegraph-loader)。 +4. **灰度切换**:Cypher 能表达的查询保持不动, translator 不支持的改写为 + Gremlin(等价写法见 [对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法))。 + +### 已知限制速查 + +- Cypher 语句不支持参数绑定、多语句脚本与 `CALL` 过程。 +- 转译器最后一次发布是 2019-11(1.0.4),其自身 TCK 报告为 + 879 通过 / 79 失败(约 91.7%)—— 未覆盖的语法会在翻译期报错。 +- 不支持的写法始终可以用等价 Gremlin 表达 —— 见 + [HugeGraph Cypher 的对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法)。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md new file mode 100644 index 0000000000..c516deb38e --- /dev/null +++ b/content/en/docs/language/cypher-compatibility.md @@ -0,0 +1,59 @@ +--- +title: "Cypher Compatibility" +linkTitle: "Cypher Compatibility" +weight: 3 +--- + +### Scope of this page + +HugeGraph executes Cypher by translating statements to Gremlin through the +[`cypher-for-gremlin`](https://github.com/opencypher/cypher-for-gremlin) +transpiler (`org.opencypher.gremlin:translation:1.0.4`, released 2019-11-05). +Cypher coverage in HugeGraph therefore equals what that translator implements +of openCypher 9 — see [HugeGraph Cypher](/docs/language/hugegraph-cypher/) for +usage and [Known limitations](/docs/language/hugegraph-cypher/#known-limitations) +for the short list. + +The transpiler's own conformance self-report for 1.0.4 is **879 pass / 79 fail +(~91.7%)** of the openCypher TCK scenario set it targets. The matrix below +classifies features by the best available evidence; rows are not a substitute +for testing your own workload. + +### Feature matrix + +| openCypher feature | Status | Evidence tier | Notes / Gremlin workaround | +|---|---|---|---| +| `MATCH` + `WHERE` + `RETURN` (node patterns) | ✅ Works | Documented examples | [Language guide](/docs/language/hugegraph-cypher/) | +| Relationship patterns `(a)-[:KNOWS]->(b)` | ✅ Works | Documented examples | — | +| `ORDER BY` / `LIMIT` / `SKIP` | ✅ Works | Documented examples | — | +| `CREATE` vertex / edge, `SET` / `REMOVE`, `DELETE` / `DETACH DELETE` | ✅ Works | Documented examples | — | +| Aggregations (`count`, `sum`, `min`, `max`, `avg`) | ✅ Works | Documented examples | — | +| `MERGE` (basic) | ⚠️ Partial | Transpiler report | `MERGE ... ON CREATE SET` / `ON MATCH SET` not translated → check-then-create pattern via Gremlin | +| Variable-length paths `(a)-[:KNOWS*1..3]->(b)` | ⚠️ Untested | — | Prefer `traverser` REST APIs (k-out, paths) or Gremlin `repeat()` | +| `OPTIONAL MATCH`, `WITH`, `UNWIND` | ⚠️ Untested | — | Test before relying on them; fall back to Gremlin | +| String / math functions | ⚠️ Partial | Transpiler report | Subset of openCypher 9 functions; unsupported ones fail at translation time | +| `date()` / `datetime()` functions | ❌ Not supported | Issue reports | Compute timestamps client-side and pass as literal values | +| Regex `=~` and `NOT (... IN ...)` forms | ❌ Not supported | Issue reports | Filter client-side or via Gremlin predicates (`TextP.regex`) | +| Map projection `n { .name, .age }` | ❌ Not supported | Issue reports | Return the node or explicit properties | +| Query parameters (`$param`) | ❌ Not supported | API surface (`CypherAPI` accepts statement string only) | Escape/sanitize values client-side before interpolating | +| `CALL` procedures (graph algorithms) | ❌ Not supported | API surface | Use [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin | +| Multi-statement scripts | ❌ Not supported | API surface | One statement per request | +| Schema DDL in Cypher (`CREATE INDEX`, constraints) | ❌ Not supported | Architecture | Create schema via the [schema REST APIs](/docs/clients/restful-api/schema/) | +| `EXPLAIN` / `PROFILE` | ❌ Not supported | API surface | Use Gremlin `profile()` on the traversal API | + +Legend: ✅ verified on the documented path · ⚠️ partial or not verified on +HugeGraph — test first · ❌ not reachable through the Cypher API. + +### Failure behaviour + +Unsupported constructs fail at translation time; the response +`status.message` carries the transpiler error. When a statement cannot be +expressed, the equivalent Gremlin traversal always works — see the +[equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents). + +### Improving this page + +This matrix is enriched as conformance evidence improves. Running the +openCypher TCK against a live HugeGraph server (and publishing the pass/fail +matrix) is the tracked follow-up that converts ⚠️ rows into definitive +answers. diff --git a/content/en/docs/language/migrate-from-neo4j.md b/content/en/docs/language/migrate-from-neo4j.md new file mode 100644 index 0000000000..90a6ed21e8 --- /dev/null +++ b/content/en/docs/language/migrate-from-neo4j.md @@ -0,0 +1,60 @@ +--- +title: "Migrating from Neo4j" +linkTitle: "Migrating from Neo4j" +weight: 4 +--- + +### Who this page is for + +Neo4j users evaluating HugeGraph. HugeGraph's Cypher coverage is defined by +the [`cypher-for-gremlin`](https://github.com/opencypher/cypher-for-gremlin) +translator and is not 1:1 with Neo4j — see the +[Cypher compatibility matrix](/docs/language/cypher-compatibility/) for the +feature-level differences and +[HugeGraph Cypher](/docs/language/hugegraph-cypher/) for usage. + +### What carries over directly + +| Neo4j concept | HugeGraph equivalent | +|---|---| +| Property graph model (nodes / relationships / properties) | Same — vertex labels / edge labels / properties | +| Core Cypher: `MATCH`/`WHERE`/`RETURN`/`CREATE`/`SET`/`DELETE` | Works as-is (REST `/cypher` endpoint or Java client `CypherManager`) | +| Simple aggregations (`count`/`sum`/`min`/`max`/`avg`) | Works as-is | +| Traversal-heavy queries | Gremlin traversals or the [traverser REST APIs](/docs/clients/restful-api/traverser/) (k-out, shortest path, personalrank, ...) | + +### Habits you need to change + +| In Neo4j | In HugeGraph | +|---|---| +| `CREATE INDEX` / `CREATE CONSTRAINT` | Create indexes/constraints through the [schema REST APIs](/docs/clients/restful-api/schema/); Cypher carries no DDL | +| Implicit schema (add properties freely) | **Strong schema**: define VertexLabel / EdgeLabel / PropertyKey before writing data | +| Parameterized queries `$param` | Not supported — escape/validate values client-side and interpolate literals | +| `CALL dbms.*` / `CALL algo.*` procedures | Equivalent capabilities live in the [traverser](/docs/clients/restful-api/traverser/), [task](/docs/clients/restful-api/task/), and other REST APIs | +| Driver: Neo4j Bolt driver | [hugegraph-client](/docs/clients/hugegraph-client/) (`CypherManager`) or any HTTP client | +| Transaction boundaries inside a Cypher statement | One statement per request; bulk writes use the [Loader](/docs/guides/toolchain/) or bulkport | + +### Suggested migration path + +1. **Inventory your queries**: classify the Cypher in your application against + the [compatibility matrix](/docs/language/cypher-compatibility/) into + "works as-is / rewrite as Gremlin / switch to a REST API". +2. **Create the schema first**: define VertexLabel / EdgeLabel / PropertyKey + and indexes through the schema API — HugeGraph requires the schema to + exist before data is written. +3. **Import data**: REST for small datasets; the + [HugeGraph Loader](https://github.com/apache/hugegraph-toolchain/tree/master/hugegraph-loader) + for bulk loads. +4. **Switch incrementally**: keep the queries Cypher can express, and rewrite + translator-unsupported constructs as Gremlin — the + [equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents) + shows the mapping. + +### Known limitations at a glance + +- Cypher statements support neither parameter binding, multi-statement + scripts, nor `CALL` procedures. +- The translator's last release is 2019-11 (1.0.4); its own TCK self-report is + 879 pass / 79 fail (~91.7%) — uncovered syntax fails at translation time. +- Anything unsupported can always be expressed as an equivalent Gremlin + traversal — see the + [equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents). diff --git a/data/docs_nav.json b/data/docs_nav.json index 184bd5df63..49c1b8b959 100644 --- a/data/docs_nav.json +++ b/data/docs_nav.json @@ -218,6 +218,12 @@ }, { "page": "/docs/language/hugegraph-cypher" + }, + { + "page": "/docs/language/cypher-compatibility" + }, + { + "page": "/docs/language/migrate-from-neo4j" } ] }, @@ -674,6 +680,16 @@ "page": "/docs/language/hugegraph-cypher", "url": "/docs/language/hugegraph-cypher/", "children": [] + }, + { + "page": "/docs/language/cypher-compatibility", + "url": "/docs/language/cypher-compatibility/", + "children": [] + }, + { + "page": "/docs/language/migrate-from-neo4j", + "url": "/docs/language/migrate-from-neo4j/", + "children": [] } ] }, @@ -1334,6 +1350,16 @@ "@group/develop", "/docs/language/", "/docs/language/hugegraph-cypher/" + ], + "/docs/language/cypher-compatibility/": [ + "@group/develop", + "/docs/language/", + "/docs/language/cypher-compatibility/" + ], + "/docs/language/migrate-from-neo4j/": [ + "@group/develop", + "/docs/language/", + "/docs/language/migrate-from-neo4j/" ] }, "children_by_url": { @@ -1412,7 +1438,9 @@ ], "/docs/language/": [ "/docs/language/hugegraph-gremlin", - "/docs/language/hugegraph-cypher" + "/docs/language/hugegraph-cypher", + "/docs/language/cypher-compatibility", + "/docs/language/migrate-from-neo4j" ], "/docs/config/": [ "/docs/config/config-guide", diff --git a/data/version_routes.json b/data/version_routes.json index 3238ec3132..6d9e508372 100644 --- a/data/version_routes.json +++ b/data/version_routes.json @@ -1512,6 +1512,34 @@ "1.5": null, "1.3": null, "1.0": null + }, + "cn:language/cypher-compatibility": { + "latest": "cn/docs/language/cypher-compatibility/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, + "en:language/cypher-compatibility": { + "latest": "docs/language/cypher-compatibility/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, + "cn:language/migrate-from-neo4j": { + "latest": "cn/docs/language/migrate-from-neo4j/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, + "en:language/migrate-from-neo4j": { + "latest": "docs/language/migrate-from-neo4j/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null } }, "equivalents": [ From 36a132d1bd50b727c15ac6a0bd5d62c9bb7dffcb Mon Sep 17 00:00:00 2001 From: imbajin Date: Fri, 25 Sep 2026 12:28:23 +0800 Subject: [PATCH 03/17] docs: record cypher baseline results - Record the nine-request legacy CRUD sample and tested runtime. - Describe delayed failed-write residue and the failed atomicity check. - Link the evidence and limit claims to the observed scope. --- .../cn/docs/language/cypher-compatibility.md | 16 ++++++++++++++++ .../en/docs/language/cypher-compatibility.md | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index cedd258d90..77416f9dcc 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -40,6 +40,22 @@ openCypher 9 子集 —— 用法见 [HugeGraph Cypher](/cn/docs/language/hugegr 图例:✅ 已在文档路径验证 · ⚠️ 部分支持或未在 HugeGraph 验证 —— 先测试 · ❌ Cypher API 不可达。 +### 开发分支实测 + +在 +[`hugegraph/hugegraph@27a7c9b42274d6d4f95eabed6d2051d393ae0eaf`](https://github.com/hugegraph/hugegraph/commit/27a7c9b42274d6d4f95eab6d2051d393ae0eaf) +上,使用 Java `17.0.20.1`、TinkerPop `3.8.1`、RocksDB 和 `translation-1.0.4`, +对实际 Cypher 路径进行了 9 条 Cypher 请求的样例验证。legacy GET 和纯文本 POST、 +基础节点与边的 `CREATE`、`SET`、`DELETE` 请求以及 native REST 回读通过。 + +本次单语句写原子性检查未通过。第一轮中,失败的双节点 `CREATE` 后即时 +native 回读未见前缀;后续聚合/排序读暴露了前缀,native 全量列表也予以 +确认。第二轮复现中,即时 native 回读和之后 7 次成功的只读 count/native +回读均未见前缀;第 8 次 count 后,native 全量列表首次显示 +`baseline_repro_prefix_v2`。两轮都观察到残留;触发条件仍在调查,尚无修复 +验证。本样例不能证明完整写事务或 openCypher 兼容性。详见[本 PR 的基线 +结果](https://github.com/apache/hugegraph-doc/pull/499#issuecomment-5826172378)。 + ### 失败行为 不支持的写法在翻译期报错,响应 `status.message` 携带转译器错误。无法表达的 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index c516deb38e..29a1ee9976 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -44,6 +44,25 @@ for testing your own workload. Legend: ✅ verified on the documented path · ⚠️ partial or not verified on HugeGraph — test first · ❌ not reachable through the Cypher API. +### Development-branch runtime check + +A sample of nine Cypher requests was run at +[`hugegraph/hugegraph@27a7c9b42274d6d4f95eabed6d2051d393ae0eaf`](https://github.com/hugegraph/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf) +with Java `17.0.20.1`, TinkerPop `3.8.1`, RocksDB, and `translation-1.0.4`. The +legacy GET and raw-text POST paths, basic node and edge `CREATE`, `SET`, and +`DELETE` requests, and native REST readback passed. + +The tested single-statement write-atomicity check failed. After a failed +two-node `CREATE`, the first run's immediate native readback did not show the +prefix; later aggregate/sort reads exposed it, and a full native listing +confirmed it. In a second reproduction, neither the immediate native read nor +seven subsequent successful read-only count/native reads showed the prefix. It +appeared on the eighth count and in the following full native listing as +`baseline_repro_prefix_v2`. The residue appeared in both runs. Its trigger is +under investigation and no fix is verified. This sample does not establish +full write-transaction or openCypher compatibility. See [the baseline results +on this PR](https://github.com/apache/hugegraph-doc/pull/499#issuecomment-5826172378). + ### Failure behaviour Unsupported constructs fail at translation time; the response From 2d6b6275fae691de3167d5fd6f2627da04733286 Mon Sep 17 00:00:00 2001 From: imbajin Date: Fri, 25 Sep 2026 14:01:39 +0800 Subject: [PATCH 04/17] docs: verify core cypher compatibility - Link measured Java 17, TinkerPop 3.8.1, and RocksDB results to code PR #238. - Document parameter requests and the failed-write regression. - Limit compatibility claims to tested cases; mark advanced features unverified. --- .../cn/docs/language/cypher-compatibility.md | 132 ++++++++-------- .../en/docs/language/cypher-compatibility.md | 148 +++++++++--------- 2 files changed, 146 insertions(+), 134 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index 77416f9dcc..218c8c185f 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -4,65 +4,73 @@ linkTitle: "Cypher 兼容性" weight: 3 --- -### 本页范围 - -HugeGraph 通过 [`cypher-for-gremlin`](https://github.com/opencypher/cypher-for-gremlin) -转译器(`org.opencypher.gremlin:translation:1.0.4`,发布于 2019-11-05)把 Cypher -翻译成 Gremlin 执行。因此 HugeGraph 的 Cypher 覆盖面等于该转译器实现的 -openCypher 9 子集 —— 用法见 [HugeGraph Cypher](/cn/docs/language/hugegraph-cypher/), -简版限制见[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 - -转译器 1.0.4 自报的 conformance 数据为 **879 通过 / 79 失败(约 91.7%)**。 -下表按现有证据对特性分级;它不能替代对你的真实负载做测试。 - -### 特性矩阵 - -| openCypher 特性 | 状态 | 证据层级 | 说明 / Gremlin 替代 | -|---|---|---|---| -| `MATCH` + `WHERE` + `RETURN`(节点模式) | ✅ 可用 | 文档示例 | [语言指南](/cn/docs/language/hugegraph-cypher/) | -| 关系模式 `(a)-[:KNOWS]->(b)` | ✅ 可用 | 文档示例 | — | -| `ORDER BY` / `LIMIT` / `SKIP` | ✅ 可用 | 文档示例 | — | -| `CREATE` 点/边、`SET` / `REMOVE`、`DELETE` / `DETACH DELETE` | ✅ 可用 | 文档示例 | — | -| 聚合(`count`、`sum`、`min`、`max`、`avg`) | ✅ 可用 | 文档示例 | — | -| `MERGE`(基础) | ⚠️ 部分 | 转译器报告 | `MERGE ... ON CREATE SET` / `ON MATCH SET` 不支持 → 用 Gremlin 先查后建 | -| 变长路径 `(a)-[:KNOWS*1..3]->(b)` | ⚠️ 未验证 | — | 优先用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin `repeat()` | -| `OPTIONAL MATCH`、`WITH`、`UNWIND` | ⚠️ 未验证 | — | 使用前先测试;可回退 Gremlin | -| 字符串 / 数学函数 | ⚠️ 部分 | 转译器报告 | 只覆盖 openCypher 9 函数子集;不支持的在翻译期报错 | -| `date()` / `datetime()` 函数 | ❌ 不支持 | Issue 记录 | 在客户端算好时间戳后以字面量传入 | -| 正则 `=~` 与 `NOT (... IN ...)` | ❌ 不支持 | Issue 记录 | 客户端过滤,或用 Gremlin 谓词(`TextP.regex`) | -| Map projection `n { .name, .age }` | ❌ 不支持 | Issue 记录 | 返回节点本身或显式属性 | -| 查询参数(`$param`) | ❌ 不支持 | API 面(`CypherAPI` 只接受语句字符串) | 在客户端转义/校验后拼接字面量 | -| `CALL` 过程(图算法) | ❌ 不支持 | API 面 | 使用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin | -| 多语句脚本 | ❌ 不支持 | API 面 | 每次请求一条语句 | -| Cypher 里的 DDL(`CREATE INDEX`、约束) | ❌ 不支持 | 架构 | 通过 [schema REST API](/cn/docs/clients/restful-api/schema/) 建索引/约束 | -| `EXPLAIN` / `PROFILE` | ❌ 不支持 | API 面 | 在 Gremlin 遍历上使用 `profile()` | - -图例:✅ 已在文档路径验证 · ⚠️ 部分支持或未在 HugeGraph 验证 —— 先测试 · -❌ Cypher API 不可达。 - -### 开发分支实测 - -在 -[`hugegraph/hugegraph@27a7c9b42274d6d4f95eabed6d2051d393ae0eaf`](https://github.com/hugegraph/hugegraph/commit/27a7c9b42274d6d4f95eab6d2051d393ae0eaf) -上,使用 Java `17.0.20.1`、TinkerPop `3.8.1`、RocksDB 和 `translation-1.0.4`, -对实际 Cypher 路径进行了 9 条 Cypher 请求的样例验证。legacy GET 和纯文本 POST、 -基础节点与边的 `CREATE`、`SET`、`DELETE` 请求以及 native REST 回读通过。 - -本次单语句写原子性检查未通过。第一轮中,失败的双节点 `CREATE` 后即时 -native 回读未见前缀;后续聚合/排序读暴露了前缀,native 全量列表也予以 -确认。第二轮复现中,即时 native 回读和之后 7 次成功的只读 count/native -回读均未见前缀;第 8 次 count 后,native 全量列表首次显示 -`baseline_repro_prefix_v2`。两轮都观察到残留;触发条件仍在调查,尚无修复 -验证。本样例不能证明完整写事务或 openCypher 兼容性。详见[本 PR 的基线 -结果](https://github.com/apache/hugegraph-doc/pull/499#issuecomment-5826172378)。 - -### 失败行为 - -不支持的写法在翻译期报错,响应 `status.message` 携带转译器错误。无法表达的 -语句始终有等价 Gremlin 写法 —— 见 -[对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法)。 - -### 持续完善 - -随着 conformance 证据增加,本矩阵会持续更新。针对真实 HugeGraph 服务运行 -openCypher TCK 并公布通过/失败矩阵,是把 ⚠️ 行变成确定答案的既定后续工作。 +### 范围 + +本页记录当前 Cypher 开发改动实际验证过的用例,不代表完整支持 openCypher 或 Neo4j,也不代表所有已发布 +版本的 HugeGraph 都具备相同行为。测试代码基于 +[`hugegraph/hugegraph@27a7c9b`](https://github.com/hugegraph/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf), +使用 Java `17.0.20.1`、TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。 + +接口路径为 `/graphspaces/{graphspace}/graphs/{graph}/cypher`。一般用法见 +[HugeGraph Cypher 指南](/cn/docs/language/hugegraph-cypher/)。 + +### 请求形式与参数 + +| 请求 | 已验证行为 | 测试方法 | +|---|---|---| +| `GET ?cypher=` | 保留原有查询参数形式 | `testGet` | +| `POST application/json`,请求体为原始 Cypher 文本 | 保留旧的原始文本请求形式 | `testPost` | +| `POST text/plain`,请求体为原始 Cypher 文本 | 支持纯文本请求 | `testPlainTextPost` | +| `POST application/json`,请求体为 JSON 对象 | 查询语句与参数分开传入 | `testParameters` | + +```json +{ + "cypher": "MATCH (n:cypher_person) WHERE n.name = $name RETURN n.name", + "parameters": {"name": "marko"} +} +``` + +JSON 对象中的 `cypher` 必须是非空字符串;`parameters` 若提供,必须是对象。省略 `parameters` 表示空参数表。 +语句引用了未提供的参数时会报执行错误;显式传入 `null` 是有效值。测试覆盖字符串、数字、布尔值、引号和换行, +参数名 `id` 与 `label`,以及默认最多 16 个参数。参数值会作为绑定值传递,不会改写查询文本。 + +同时检查 HTTP 状态和响应体的 `status.code`:执行错误可能仍返回 HTTP 200,但 `status.code` 为 400,结果数据为 null。 + +### 已验证行为 + +API 测试夹具使用强类型 Schema,并为 `city` 建立 `SECONDARY` 索引、为 `age` 建立 `RANGE` 索引。验收结论仅限于下列用例: + +| 范围 | 测试用例 | 测试方法 | +|---|---|---| +| 查询 | 标签扫描、相等和范围条件、布尔组合、有向一跳和两跳关系、空结果 | `testGet`、`testExactReadsAndPredicates`、`testRelationQuery` | +| 结果 | 别名、标量和节点值、嵌套值、关系 ID、路径结构、null 与缺失属性 | `testReturnNodeIdAsPrimitiveValue`、`testReturnNodeDoesNotLeakInternalIdTypes`、`testReturnNestedIdDoesNotLeakInternalIdTypes`、`testReturnRelationIdDoesNotLeakInternalIdTypes`、`testReturnPathShape`、`testNullAndMissingProperty` | +| 聚合和分页 | `DISTINCT`、`count`/`sum`/`min`/`max`/`avg`、`ORDER BY`、`SKIP`、`LIMIT` | `testDuplicatesDistinctAndPagination`、`testAggregates` | +| 写入 | 创建顶点和边、修改属性、删除边和顶点;通过原生 REST 读取检查状态 | `testCreate`、`testCreateSetAndDeleteWithNativeReadback` | +| 失败写入 | 拒绝双顶点 `CREATE` 后,连续 32 次查询和原生读取均未发现残留 | `testFailedWriteDoesNotLeakIntoLaterRequests` | +| 错误与路由 | 非法语法和请求结构、参数键、Schema 值、认证及图路由 | `testInvalidRequests`、`testRejectInvalidQuery`、`testRejectInvalidBindingShapeAndKeys`、`testAuthenticationAndGraphRouting`、`testSpecifiedGraphRouting` | + +`CypherApiTest` 通过 20/20,`CypherClientTest` 通过 7/7,`CypherOpProcessorTest` 通过 4/4,均无跳过。 +相关 Gremlin 测试通过 10 项,另有一项 `testClearAndInit` 因后端不共享而不适用;Login 测试通过 3/3。 +EditorConfig 格式检查和仓库根目录 clean compile 均通过。代码改动位于 +[草稿 PR #238](https://github.com/hugegraph/hugegraph/pull/238)。固定测试提交 +[`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md) +中的兼容性说明包含逐方法测试映射和验证记录。该提交的测试源码: +[`CypherApiTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java)、 +[`CypherClientTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java) +和 +[`CypherOpProcessorTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java)。 + +### 基线故障与当前修复 + +在上述固定基线提交中,失败的双顶点 `CREATE` 在两次观察中都留下了延迟可见的残留。第一次运行中,即时原生读取未发现前缀, +但后续聚合/排序查询暴露了前缀,原生全量列表也确认了它。第二次复现时,即时原生读取和之后 7 次 count/原生读取均未见前缀; +第 8 次 count 后才出现。原始基线证据保留在 +[基线报告](https://github.com/apache/hugegraph-doc/pull/499#issuecomment-5826172378)。 + +当前开发改动通过了 `testFailedWriteDoesNotLeakIntoLaterRequests`:针对该夹具,原生读取和后续 32 轮查询/原生读取均确认无残留。 +这只验证了已报告的失败场景及当前测试栈,不能据此推断所有回滚路径、跨请求事务语义、所有语句或后端的写原子性。 + +### 本次未验证 + +本次测试范围之外的高级语法和行为仍未验证,包括 `MERGE`、`OPTIONAL MATCH`、`WITH`、`UNWIND`、`UNION`、变长路径、 +广泛的函数覆盖、过程调用、Cypher Schema DDL、`EXPLAIN`/`PROFILE`、HStore、Bolt、跨请求事务和性能。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index 29a1ee9976..85934e7e11 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -4,75 +4,79 @@ linkTitle: "Cypher Compatibility" weight: 3 --- -### Scope of this page - -HugeGraph executes Cypher by translating statements to Gremlin through the -[`cypher-for-gremlin`](https://github.com/opencypher/cypher-for-gremlin) -transpiler (`org.opencypher.gremlin:translation:1.0.4`, released 2019-11-05). -Cypher coverage in HugeGraph therefore equals what that translator implements -of openCypher 9 — see [HugeGraph Cypher](/docs/language/hugegraph-cypher/) for -usage and [Known limitations](/docs/language/hugegraph-cypher/#known-limitations) -for the short list. - -The transpiler's own conformance self-report for 1.0.4 is **879 pass / 79 fail -(~91.7%)** of the openCypher TCK scenario set it targets. The matrix below -classifies features by the best available evidence; rows are not a substitute -for testing your own workload. - -### Feature matrix - -| openCypher feature | Status | Evidence tier | Notes / Gremlin workaround | -|---|---|---|---| -| `MATCH` + `WHERE` + `RETURN` (node patterns) | ✅ Works | Documented examples | [Language guide](/docs/language/hugegraph-cypher/) | -| Relationship patterns `(a)-[:KNOWS]->(b)` | ✅ Works | Documented examples | — | -| `ORDER BY` / `LIMIT` / `SKIP` | ✅ Works | Documented examples | — | -| `CREATE` vertex / edge, `SET` / `REMOVE`, `DELETE` / `DETACH DELETE` | ✅ Works | Documented examples | — | -| Aggregations (`count`, `sum`, `min`, `max`, `avg`) | ✅ Works | Documented examples | — | -| `MERGE` (basic) | ⚠️ Partial | Transpiler report | `MERGE ... ON CREATE SET` / `ON MATCH SET` not translated → check-then-create pattern via Gremlin | -| Variable-length paths `(a)-[:KNOWS*1..3]->(b)` | ⚠️ Untested | — | Prefer `traverser` REST APIs (k-out, paths) or Gremlin `repeat()` | -| `OPTIONAL MATCH`, `WITH`, `UNWIND` | ⚠️ Untested | — | Test before relying on them; fall back to Gremlin | -| String / math functions | ⚠️ Partial | Transpiler report | Subset of openCypher 9 functions; unsupported ones fail at translation time | -| `date()` / `datetime()` functions | ❌ Not supported | Issue reports | Compute timestamps client-side and pass as literal values | -| Regex `=~` and `NOT (... IN ...)` forms | ❌ Not supported | Issue reports | Filter client-side or via Gremlin predicates (`TextP.regex`) | -| Map projection `n { .name, .age }` | ❌ Not supported | Issue reports | Return the node or explicit properties | -| Query parameters (`$param`) | ❌ Not supported | API surface (`CypherAPI` accepts statement string only) | Escape/sanitize values client-side before interpolating | -| `CALL` procedures (graph algorithms) | ❌ Not supported | API surface | Use [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin | -| Multi-statement scripts | ❌ Not supported | API surface | One statement per request | -| Schema DDL in Cypher (`CREATE INDEX`, constraints) | ❌ Not supported | Architecture | Create schema via the [schema REST APIs](/docs/clients/restful-api/schema/) | -| `EXPLAIN` / `PROFILE` | ❌ Not supported | API surface | Use Gremlin `profile()` on the traversal API | - -Legend: ✅ verified on the documented path · ⚠️ partial or not verified on -HugeGraph — test first · ❌ not reachable through the Cypher API. - -### Development-branch runtime check - -A sample of nine Cypher requests was run at -[`hugegraph/hugegraph@27a7c9b42274d6d4f95eabed6d2051d393ae0eaf`](https://github.com/hugegraph/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf) -with Java `17.0.20.1`, TinkerPop `3.8.1`, RocksDB, and `translation-1.0.4`. The -legacy GET and raw-text POST paths, basic node and edge `CREATE`, `SET`, and -`DELETE` requests, and native REST readback passed. - -The tested single-statement write-atomicity check failed. After a failed -two-node `CREATE`, the first run's immediate native readback did not show the -prefix; later aggregate/sort reads exposed it, and a full native listing -confirmed it. In a second reproduction, neither the immediate native read nor -seven subsequent successful read-only count/native reads showed the prefix. It -appeared on the eighth count and in the following full native listing as -`baseline_repro_prefix_v2`. The residue appeared in both runs. Its trigger is -under investigation and no fix is verified. This sample does not establish -full write-transaction or openCypher compatibility. See [the baseline results -on this PR](https://github.com/apache/hugegraph-doc/pull/499#issuecomment-5826172378). - -### Failure behaviour - -Unsupported constructs fail at translation time; the response -`status.message` carries the transpiler error. When a statement cannot be -expressed, the equivalent Gremlin traversal always works — see the -[equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents). - -### Improving this page - -This matrix is enriched as conformance evidence improves. Running the -openCypher TCK against a live HugeGraph server (and publishing the pass/fail -matrix) is the tracked follow-up that converts ⚠️ rows into definitive -answers. +### Scope + +This page records the cases verified for the current Cypher development change. It does not claim full +openCypher or Neo4j compatibility, or compatibility across every released HugeGraph version. The tested +working tree is based on [`hugegraph/hugegraph@27a7c9b`](https://github.com/hugegraph/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf) +and uses Java `17.0.20.1`, TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. + +The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage is covered in the +[HugeGraph Cypher guide](/docs/language/hugegraph-cypher/). + +### Request forms and parameters + +| Request | Verified contract | Test method | +|---|---|---| +| `GET ?cypher=` | Existing query-string form | `testGet` | +| `POST application/json` with raw Cypher text | Legacy raw-body form remains available | `testPost` | +| `POST text/plain` with raw Cypher text | Plain-text form | `testPlainTextPost` | +| `POST application/json` with a JSON object | Query and bindings are sent separately | `testParameters` | + +```json +{ + "cypher": "MATCH (n:cypher_person) WHERE n.name = $name RETURN n.name", + "parameters": {"name": "marko"} +} +``` + +For the JSON-object form, `cypher` must be a nonblank string and `parameters`, if present, must be an object. +Omitting `parameters` means an empty map. A referenced but missing binding is an execution error; an explicit +null value is valid. Tests cover string, number, and boolean values, quotes and newlines, the binding names +`id` and `label`, and the default limit of 16 parameters. Values remain bindings and do not alter query text. + +Check both the HTTP status and the response body's `status.code`: an execution failure can retain HTTP 200 +while returning `status.code` 400 and null result data. + +### Verified behavior + +The API fixture uses a strong schema, with a `SECONDARY` index on `city` and a `RANGE` index on `age`. +Acceptance results are limited to these test cases: + +| Area | Tested cases | Test methods | +|---|---|---| +| Reads | Label scans; equality and range predicates; boolean combinations; directed one- and two-hop patterns; empty results | `testGet`, `testExactReadsAndPredicates`, `testRelationQuery` | +| Results | Aliases, scalar and node values, nested values, relationship ids, path shape, null and missing properties | `testReturnNodeIdAsPrimitiveValue`, `testReturnNodeDoesNotLeakInternalIdTypes`, `testReturnNestedIdDoesNotLeakInternalIdTypes`, `testReturnRelationIdDoesNotLeakInternalIdTypes`, `testReturnPathShape`, `testNullAndMissingProperty` | +| Aggregation and pagination | `DISTINCT`, `count`/`sum`/`min`/`max`/`avg`, `ORDER BY`, `SKIP`, and `LIMIT` | `testDuplicatesDistinctAndPagination`, `testAggregates` | +| Writes | Vertex and edge `CREATE`, property `SET`, edge and vertex `DELETE`; state checked through native REST reads | `testCreate`, `testCreateSetAndDeleteWithNativeReadback` | +| Failed write | A rejected two-vertex `CREATE` left no residue during 32 subsequent query and native-read checks | `testFailedWriteDoesNotLeakIntoLaterRequests` | +| Errors and routing | Invalid syntax and request shape, binding keys, schema values, authentication, and graph routing | `testInvalidRequests`, `testRejectInvalidQuery`, `testRejectInvalidBindingShapeAndKeys`, `testAuthenticationAndGraphRouting`, `testSpecifiedGraphRouting` | + +`CypherApiTest` passed 20/20, `CypherClientTest` 7/7, and `CypherOpProcessorTest` 4/4, with no skips. +Related Gremlin tests passed 10 cases with one inapplicable `testClearAndInit` skip for a non-shared backend; +Login tests passed 3/3. EditorConfig formatting and the repository-root clean compile passed. +The code change is in [draft PR #238](https://github.com/hugegraph/hugegraph/pull/238). The compatibility +note at tested source commit [`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md) +contains the method-level mapping and verification record. Test sources at that commit: +[`CypherApiTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java), +[`CypherClientTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java), +and [`CypherOpProcessorTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java). + +### Baseline failure and current fix + +At the pinned baseline commit above, a failed two-vertex `CREATE` left delayed residue in two observations. +In the first run, an immediate native read missed the prefix, but later aggregate/sort reads exposed it and +a full native listing confirmed it. In the second reproduction, immediate native reads and seven later +count/native-read checks showed no prefix; it appeared after the eighth count. The original baseline evidence remains in +[the baseline report](https://github.com/apache/hugegraph-doc/pull/499#issuecomment-5826172378). + +The current development change passes `testFailedWriteDoesNotLeakIntoLaterRequests`: native reads and 32 +later query/native-read checks confirm that this fixture leaves no residue. This verifies the reported +failure case on the tested stack; it does not establish every rollback path, cross-request transaction +semantics, or full write atomicity for all statements and backends. + +### Not verified by this change + +Advanced constructs and behaviors outside the test cases above remain unverified. This includes `MERGE`, +`OPTIONAL MATCH`, `WITH`, `UNWIND`, `UNION`, variable-length paths, broad function coverage, procedures, +Cypher schema DDL, `EXPLAIN`/`PROFILE`, HStore, Bolt, cross-request transactions, and performance. From debb31848870a38e000826beffe5beab37f0c139 Mon Sep 17 00:00:00 2001 From: n24q02m Date: Sat, 26 Sep 2026 02:27:30 +0700 Subject: [PATCH 05/17] docs: address cypher page review feedback - guide: MERGE ON CREATE/ON MATCH, =~ and NOT ... IN translate but are unverified end-to-end; only map projections and datetime() fail translation - guide: $param statement runs with null binding (empty result), not an error; JSON-bound parameters land via hugegraph/hugegraph#238 - guide: add EXPLAIN tip (translated Gremlin in result.data[0].translation), PROFILE unsupported - migration: point Loader links at /docs/quickstart/toolchain/hugegraph-loader/, drop undefined 'bulkport'; scope the Gremlin-fallback claim to query constructs (DDL and CALL go through REST APIs) - migration: qualify parameter binding by version in habits table and limits - compatibility: drop 'draft' label from PR #238 (now open) - version_routes.json: insert the 6 new page entries in sorted locale order --- .../cn/docs/language/cypher-compatibility.md | 2 +- content/cn/docs/language/hugegraph-cypher.md | 6 +- .../cn/docs/language/migrate-from-neo4j.md | 18 ++-- .../en/docs/language/cypher-compatibility.md | 2 +- content/en/docs/language/hugegraph-cypher.md | 6 +- .../en/docs/language/migrate-from-neo4j.md | 20 +++-- data/version_routes.json | 84 +++++++++---------- 7 files changed, 73 insertions(+), 65 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index 218c8c185f..540e64ffa2 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -52,7 +52,7 @@ API 测试夹具使用强类型 Schema,并为 `city` 建立 `SECONDARY` 索引 `CypherApiTest` 通过 20/20,`CypherClientTest` 通过 7/7,`CypherOpProcessorTest` 通过 4/4,均无跳过。 相关 Gremlin 测试通过 10 项,另有一项 `testClearAndInit` 因后端不共享而不适用;Login 测试通过 3/3。 EditorConfig 格式检查和仓库根目录 clean compile 均通过。代码改动位于 -[草稿 PR #238](https://github.com/hugegraph/hugegraph/pull/238)。固定测试提交 +[PR #238](https://github.com/hugegraph/hugegraph/pull/238)。固定测试提交 [`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md) 中的兼容性说明包含逐方法测试映射和验证记录。该提交的测试源码: [`CypherApiTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java)、 diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index a27caa89c3..797a3567f1 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -117,12 +117,14 @@ MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC | `MATCH (n) DETACH DELETE n` | `g.V().drop()` | | `MATCH (n:person) RETURN count(n)` | `g.V().hasLabel('person').count()` | +提示:`EXPLAIN MATCH (n:person) RETURN n` 会被接受,并在 `result.data[0].translation` 中返回翻译后的 Gremlin —— 这是获得上表等价写法的最快方式。`PROFILE` 不受支持。 + ### 已知限制 HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代的工具链。已知缺口: -- **不支持参数化查询** —— API 只接受原始语句字符串,不支持 `$param` 占位符。请在客户端先对值做转义/净化再拼接到语句中。 -- **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 `MERGE ... ON CREATE SET`、map projection、某些 `WHERE` 谓词形式如 `NOT ... IN`,以及部分 `datetime()`/正则函数)。不支持的结构会在翻译阶段报错。 +- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被求值为 `null`,查询返回空结果(或写入 null 值)。请在客户端先对值做转义/净化再拼接到语句中。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)将随 [PR #238](https://github.com/hugegraph/hugegraph/pull/238) 落地。 +- **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`=~` 正则谓词、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 - **不支持 `CALL` 过程** —— HugeGraph 的图算法(最短路径、k-out、personalrank 等)未暴露为 Cypher 过程;请改用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin。 - **每次请求仅一条语句** —— 不支持多语句脚本,请每次调用发送一条语句。 diff --git a/content/cn/docs/language/migrate-from-neo4j.md b/content/cn/docs/language/migrate-from-neo4j.md index 1dca483180..498c928da7 100644 --- a/content/cn/docs/language/migrate-from-neo4j.md +++ b/content/cn/docs/language/migrate-from-neo4j.md @@ -8,8 +8,8 @@ weight: 4 正在评估 HugeGraph 的 Neo4j 用户。HugeGraph 的 Cypher 覆盖面由 [cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) 转译器决定, -与 Neo4j 并非 1:1 等价 —— 逐项差异见 -[Cypher 兼容性矩阵](/cn/docs/language/cypher-compatibility/), +与 Neo4j 并非 1:1 等价 —— 已验证与未验证范围见 +[Cypher 兼容性说明](/cn/docs/language/cypher-compatibility/), 用法见 [HugeGraph Cypher](/cn/docs/language/hugegraph-cypher/)。 ### 可以直接带过来的部分 @@ -27,15 +27,15 @@ weight: 4 |---|---| | `CREATE INDEX` / `CREATE CONSTRAINT` | 通过 [schema REST API](/cn/docs/clients/restful-api/schema/) 建索引/约束;Cypher 不承载 DDL | | 隐式 schema(属性随意添加) | **强 schema**:先定义 VertexLabel/EdgeLabel/PropertyKey,再写数据 | -| 参数化查询 `$param` | 暂不支持 —— 在客户端转义/校验后拼接字面量 | +| 参数化查询 `$param` | 已发布版本仅发送原始语句 —— 缺失的绑定会被求值为 `null`(空结果),请在客户端校验取值;JSON 绑定参数随 [PR #238](https://github.com/hugegraph/hugegraph/pull/238) 落地 | | `CALL dbms.*` / `CALL algo.*` 过程 | 对应功能分散在 [traverser](/cn/docs/clients/restful-api/traverser/)、[task](/cn/docs/clients/restful-api/task/) 等 REST API | | 驱动:Neo4j Bolt driver | [hugegraph-client](/cn/docs/clients/hugegraph-client/)(`CypherManager`)或任意 HTTP 客户端 | -| 事务边界在 Cypher 语句内 | 每次请求一个语句;批量写入用 [Loader](/cn/docs/guides/toolchain/) 或 bulkport | +| 事务边界在 Cypher 语句内 | 每次请求一个语句;批量导入使用 [HugeGraph Loader](/cn/docs/quickstart/toolchain/hugegraph-loader/) | ### 建议的迁移路径 1. **盘点查询**:把应用里的 Cypher 按 - [兼容性矩阵](/cn/docs/language/cypher-compatibility/) 分成 + [兼容性说明](/cn/docs/language/cypher-compatibility/) 分成 "直接可用 / 需改写为 Gremlin / 需换 REST API" 三类。 2. **先建 schema**:用 schema API 建好 VertexLabel/EdgeLabel/PropertyKey 和索引 —— HugeGraph 在写入前要求 schema 存在。 @@ -46,8 +46,10 @@ weight: 4 ### 已知限制速查 -- Cypher 语句不支持参数绑定、多语句脚本与 `CALL` 过程。 +- 已发布版本不支持参数绑定(缺失的绑定会被求值为 `null`,见上表)、 + 多语句脚本与 `CALL` 过程。 - 转译器最后一次发布是 2019-11(1.0.4),其自身 TCK 报告为 879 通过 / 79 失败(约 91.7%)—— 未覆盖的语法会在翻译期报错。 -- 不支持的写法始终可以用等价 Gremlin 表达 —— 见 - [HugeGraph Cypher 的对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法)。 +- 不受支持的查询结构通常可以改写为等价的 Gremlin 遍历 —— 见 + [HugeGraph Cypher 的对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法); + schema DDL 与 `CALL` 过程请改用 REST API。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index 85934e7e11..d236f056e1 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -55,7 +55,7 @@ Acceptance results are limited to these test cases: `CypherApiTest` passed 20/20, `CypherClientTest` 7/7, and `CypherOpProcessorTest` 4/4, with no skips. Related Gremlin tests passed 10 cases with one inapplicable `testClearAndInit` skip for a non-shared backend; Login tests passed 3/3. EditorConfig formatting and the repository-root clean compile passed. -The code change is in [draft PR #238](https://github.com/hugegraph/hugegraph/pull/238). The compatibility +The code change is in [PR #238](https://github.com/hugegraph/hugegraph/pull/238). The compatibility note at tested source commit [`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md) contains the method-level mapping and verification record. Test sources at that commit: [`CypherApiTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java), diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index 8ed88a08c1..450cce8afb 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -117,12 +117,14 @@ Every Cypher statement is translated to Gremlin internally. When a Cypher featur | `MATCH (n) DETACH DELETE n` | `g.V().drop()` | | `MATCH (n:person) RETURN count(n)` | `g.V().hasLabel('person').count()` | +Tip: `EXPLAIN MATCH (n:person) RETURN n` is accepted and returns the translated Gremlin in `result.data[0].translation` — the fastest way to obtain the equivalent traversal for the table above. `PROFILE` is not supported. + ### Known limitations Cypher support in HugeGraph is bounded by the transpiler layer, which is based on openCypher 9 era tooling. Known gaps: -- **No parameterized queries** — the API accepts a raw statement string only; `$param` placeholders are not supported. Sanitize/escape values on the client side before interpolating them into the statement. -- **Partial clause coverage** — some openCypher constructs are not translated (for example `MERGE ... ON CREATE SET`, map projections, some `WHERE` predicate forms such as `NOT ... IN`, and certain `datetime()`/regex functions). Unsupported constructs fail at translation time with an error from the transpiler. +- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding evaluates to `null`, so the query returns no rows (or writes null values) rather than failing. Sanitize/escape values on the client side before interpolating them into the statement. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are on the way in [PR #238](https://github.com/hugegraph/hugegraph/pull/238). +- **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET`, `=~` regex predicates, and `NOT ... IN` do translate, but they are not verified end-to-end on HugeGraph — see the [compatibility notes](/docs/language/cypher-compatibility/). - **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. - **Single statement per request** — multi-statement scripts are not supported; send one statement per call. diff --git a/content/en/docs/language/migrate-from-neo4j.md b/content/en/docs/language/migrate-from-neo4j.md index 90a6ed21e8..6e2714c3a8 100644 --- a/content/en/docs/language/migrate-from-neo4j.md +++ b/content/en/docs/language/migrate-from-neo4j.md @@ -9,8 +9,8 @@ weight: 4 Neo4j users evaluating HugeGraph. HugeGraph's Cypher coverage is defined by the [`cypher-for-gremlin`](https://github.com/opencypher/cypher-for-gremlin) translator and is not 1:1 with Neo4j — see the -[Cypher compatibility matrix](/docs/language/cypher-compatibility/) for the -feature-level differences and +[Cypher compatibility notes](/docs/language/cypher-compatibility/) for the +verified and unverified areas and [HugeGraph Cypher](/docs/language/hugegraph-cypher/) for usage. ### What carries over directly @@ -28,15 +28,15 @@ feature-level differences and |---|---| | `CREATE INDEX` / `CREATE CONSTRAINT` | Create indexes/constraints through the [schema REST APIs](/docs/clients/restful-api/schema/); Cypher carries no DDL | | Implicit schema (add properties freely) | **Strong schema**: define VertexLabel / EdgeLabel / PropertyKey before writing data | -| Parameterized queries `$param` | Not supported — escape/validate values client-side and interpolate literals | +| Parameterized queries `$param` | Released versions send the raw statement only — a missing binding evaluates to `null` (empty result), so validate values client-side; JSON-bound parameters land in [PR #238](https://github.com/hugegraph/hugegraph/pull/238) | | `CALL dbms.*` / `CALL algo.*` procedures | Equivalent capabilities live in the [traverser](/docs/clients/restful-api/traverser/), [task](/docs/clients/restful-api/task/), and other REST APIs | | Driver: Neo4j Bolt driver | [hugegraph-client](/docs/clients/hugegraph-client/) (`CypherManager`) or any HTTP client | -| Transaction boundaries inside a Cypher statement | One statement per request; bulk writes use the [Loader](/docs/guides/toolchain/) or bulkport | +| Transaction boundaries inside a Cypher statement | One statement per request; bulk imports use the [HugeGraph Loader](/docs/quickstart/toolchain/hugegraph-loader/) | ### Suggested migration path 1. **Inventory your queries**: classify the Cypher in your application against - the [compatibility matrix](/docs/language/cypher-compatibility/) into + the [compatibility notes](/docs/language/cypher-compatibility/) into "works as-is / rewrite as Gremlin / switch to a REST API". 2. **Create the schema first**: define VertexLabel / EdgeLabel / PropertyKey and indexes through the schema API — HugeGraph requires the schema to @@ -51,10 +51,12 @@ feature-level differences and ### Known limitations at a glance -- Cypher statements support neither parameter binding, multi-statement +- Released versions support neither parameter binding (a missing binding + evaluates to `null` — see the habits table), multi-statement scripts, nor `CALL` procedures. - The translator's last release is 2019-11 (1.0.4); its own TCK self-report is 879 pass / 79 fail (~91.7%) — uncovered syntax fails at translation time. -- Anything unsupported can always be expressed as an equivalent Gremlin - traversal — see the - [equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents). +- Unsupported query constructs can typically be rewritten as Gremlin + traversals — see the + [equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents); + schema DDL and `CALL` procedures map to REST APIs instead. diff --git a/data/version_routes.json b/data/version_routes.json index 6d9e508372..04ce6c79cc 100644 --- a/data/version_routes.json +++ b/data/version_routes.json @@ -505,6 +505,20 @@ "1.3": "cn/docs/language/", "1.0": "cn/docs/language/" }, + "cn:language/cypher-compatibility": { + "latest": "cn/docs/language/cypher-compatibility/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, + "cn:language/hugegraph-cypher": { + "latest": "cn/docs/language/hugegraph-cypher/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, "cn:language/hugegraph-example": { "latest": "cn/docs/language/hugegraph-example/", "1.7": "cn/docs/language/hugegraph-example/", @@ -519,6 +533,13 @@ "1.3": "cn/docs/language/hugegraph-gremlin/", "1.0": "cn/docs/language/hugegraph-gremlin/" }, + "cn:language/migrate-from-neo4j": { + "latest": "cn/docs/language/migrate-from-neo4j/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, "cn:performance": { "latest": "cn/docs/performance/", "1.7": "cn/docs/performance/", @@ -1212,6 +1233,20 @@ "1.3": "docs/language/", "1.0": "docs/language/" }, + "en:language/cypher-compatibility": { + "latest": "docs/language/cypher-compatibility/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, + "en:language/hugegraph-cypher": { + "latest": "docs/language/hugegraph-cypher/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, "en:language/hugegraph-example": { "latest": "docs/language/hugegraph-example/", "1.7": "docs/language/hugegraph-example/", @@ -1226,6 +1261,13 @@ "1.3": "docs/language/hugegraph-gremlin/", "1.0": "docs/language/hugegraph-gremlin/" }, + "en:language/migrate-from-neo4j": { + "latest": "docs/language/migrate-from-neo4j/", + "1.7": null, + "1.5": null, + "1.3": null, + "1.0": null + }, "en:performance": { "latest": "docs/performance/", "1.7": "docs/performance/", @@ -1498,48 +1540,6 @@ "1.5": null, "1.3": null, "1.0": null - }, - "cn:language/hugegraph-cypher": { - "latest": "cn/docs/language/hugegraph-cypher/", - "1.7": null, - "1.5": null, - "1.3": null, - "1.0": null - }, - "en:language/hugegraph-cypher": { - "latest": "docs/language/hugegraph-cypher/", - "1.7": null, - "1.5": null, - "1.3": null, - "1.0": null - }, - "cn:language/cypher-compatibility": { - "latest": "cn/docs/language/cypher-compatibility/", - "1.7": null, - "1.5": null, - "1.3": null, - "1.0": null - }, - "en:language/cypher-compatibility": { - "latest": "docs/language/cypher-compatibility/", - "1.7": null, - "1.5": null, - "1.3": null, - "1.0": null - }, - "cn:language/migrate-from-neo4j": { - "latest": "cn/docs/language/migrate-from-neo4j/", - "1.7": null, - "1.5": null, - "1.3": null, - "1.0": null - }, - "en:language/migrate-from-neo4j": { - "latest": "docs/language/migrate-from-neo4j/", - "1.7": null, - "1.5": null, - "1.3": null, - "1.0": null } }, "equivalents": [ From 3599a2bdf5d623658012841c8ceaaa6932e5fae1 Mon Sep 17 00:00:00 2001 From: Nguyen Quang Minh <135627235+n24q02m@users.noreply.github.com> Date: Sat, 26 Sep 2026 10:48:48 +0700 Subject: [PATCH 06/17] docs: split cypher examples per request and qualify EXPLAIN tip --- content/cn/docs/language/hugegraph-cypher.md | 15 ++++++++++++++- content/en/docs/language/hugegraph-cypher.md | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index 797a3567f1..a77c64bd9e 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -53,14 +53,18 @@ ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.nam ```cypher // 所有名为 "marko" 的 person MATCH (n:person) WHERE n.name = 'marko' RETURN n +``` +```cypher // 投影 + 排序 + 限制条数 MATCH (n:person) WHERE n.age > 30 RETURN n.name AS name, n.age AS age ORDER BY age DESC LIMIT 10 +``` +```cypher // 关系模式 MATCH (a:person)-[:knows]->(b:person) WHERE a.name = 'marko' @@ -72,7 +76,9 @@ RETURN b.name AS friend ```cypher // 创建顶点 CREATE (n:person {name: 'josh', age: 32, city: 'beijing'}) +``` +```cypher // 创建两个顶点及它们之间的边 CREATE (a:person {name: 'peter'})-[:knows]->(b:person {name: 'lop'}) ``` @@ -92,7 +98,9 @@ REMOVE n.city MATCH (a:person)-[r:knows]->(b:person) WHERE a.name = 'peter' AND b.name = 'lop' DELETE r +``` +```cypher // 删除顶点及其所有边 MATCH (n:person) WHERE n.name = 'josh' DETACH DELETE n @@ -101,7 +109,12 @@ DETACH DELETE n #### 聚合 ```cypher +// 总数 MATCH (n:person) RETURN count(n) AS total +``` + +```cypher +// 按城市分组计数 MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC ``` @@ -117,7 +130,7 @@ MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC | `MATCH (n) DETACH DELETE n` | `g.V().drop()` | | `MATCH (n:person) RETURN count(n)` | `g.V().hasLabel('person').count()` | -提示:`EXPLAIN MATCH (n:person) RETURN n` 会被接受,并在 `result.data[0].translation` 中返回翻译后的 Gremlin —— 这是获得上表等价写法的最快方式。`PROFILE` 不受支持。 +提示:`EXPLAIN MATCH (n:person) RETURN n` 会以 `EXPLAIN` 选项解析,翻译后的 Gremlin 预期出现在 `result.data[0].translation` 中 —— 这是转译层行为,尚未在服务器上端到端验证(见[兼容性说明](/cn/docs/language/cypher-compatibility/))。它仍是起草上表等价写法的最快方式。`PROFILE` 不受支持。 ### 已知限制 diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index 450cce8afb..b579cbf042 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -53,14 +53,18 @@ The examples below assume a graph with `person` vertices (`name`, `age`, `city` ```cypher // All persons named "marko" MATCH (n:person) WHERE n.name = 'marko' RETURN n +``` +```cypher // Projection with ordering and limit MATCH (n:person) WHERE n.age > 30 RETURN n.name AS name, n.age AS age ORDER BY age DESC LIMIT 10 +``` +```cypher // Relationship pattern MATCH (a:person)-[:knows]->(b:person) WHERE a.name = 'marko' @@ -72,7 +76,9 @@ RETURN b.name AS friend ```cypher // Create a vertex CREATE (n:person {name: 'josh', age: 32, city: 'beijing'}) +``` +```cypher // Create two vertices and an edge between them CREATE (a:person {name: 'peter'})-[:knows]->(b:person {name: 'lop'}) ``` @@ -92,7 +98,9 @@ REMOVE n.city MATCH (a:person)-[r:knows]->(b:person) WHERE a.name = 'peter' AND b.name = 'lop' DELETE r +``` +```cypher // Delete a vertex and all its edges MATCH (n:person) WHERE n.name = 'josh' DETACH DELETE n @@ -101,7 +109,12 @@ DETACH DELETE n #### Aggregation ```cypher +// Total count MATCH (n:person) RETURN count(n) AS total +``` + +```cypher +// Grouped count MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC ``` @@ -117,7 +130,7 @@ Every Cypher statement is translated to Gremlin internally. When a Cypher featur | `MATCH (n) DETACH DELETE n` | `g.V().drop()` | | `MATCH (n:person) RETURN count(n)` | `g.V().hasLabel('person').count()` | -Tip: `EXPLAIN MATCH (n:person) RETURN n` is accepted and returns the translated Gremlin in `result.data[0].translation` — the fastest way to obtain the equivalent traversal for the table above. `PROFILE` is not supported. +Tip: `EXPLAIN MATCH (n:person) RETURN n` is parsed with the `EXPLAIN` option, and the translated Gremlin is expected in `result.data[0].translation` — translator-level behavior, not yet verified end-to-end on a server (see the [compatibility notes](/docs/language/cypher-compatibility/)). It remains the quickest way to draft the equivalent traversal for the table above. `PROFILE` is not supported. ### Known limitations From 6f52040de2b7613690fb6cc50aafd6aa7af031a2 Mon Sep 17 00:00:00 2001 From: Nguyen Quang Minh <135627235+n24q02m@users.noreply.github.com> Date: Thu, 1 Oct 2026 18:18:57 +0700 Subject: [PATCH 07/17] docs: scope the compatibility page to unmerged development behaviour A maintainer review flagged that the request-forms table presents forms from an unmerged change as verified released behaviour, with no release qualifier, and that it contradicts the guide's released-version `$param` statement. - state up front that no row describes a released HugeGraph version: releases expose only `GET ?cypher=` and `POST application/json` with a raw body - add an "In a released version" column; mark `text/plain` and the JSON-object bound-parameter form as introduced by hugegraph/hugegraph#238 - link the tested commit to apache/hugegraph and record that it has diverged from `master` (10 ahead, 5 behind) while `master` ships TinkerPop 3.5.1 - record that PR #238 is open and unmerged against a task branch - cross-link both locales to the guide's Known limitations section --- .../cn/docs/language/cypher-compatibility.md | 31 ++++++++++++----- .../en/docs/language/cypher-compatibility.md | 33 ++++++++++++++----- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index 540e64ffa2..214409e408 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -6,22 +6,34 @@ weight: 3 ### 范围 +**本页没有任何描述适用于已发布的 HugeGraph 版本。** 已发布版本在 +`/graphspaces/{graphspace}/graphs/{graph}/cypher` 上只提供两种请求形式:`GET ?cypher=` +和 `POST application/json`(请求体为原始 Cypher 文本)。已发布版本不接受绑定参数,引用 `$param` 的语句 +不会报错,而是返回空结果——参见[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 + 本页记录当前 Cypher 开发改动实际验证过的用例,不代表完整支持 openCypher 或 Neo4j,也不代表所有已发布 版本的 HugeGraph 都具备相同行为。测试代码基于 -[`hugegraph/hugegraph@27a7c9b`](https://github.com/hugegraph/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf), -使用 Java `17.0.20.1`、TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。 +[`apache/hugegraph@27a7c9b`](https://github.com/apache/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf), +这是一个 TinkerPop 3.8 开发提交,**不是 `master` 的祖先**:它已分叉,领先 10 个提交、落后 5 个提交。 +`master` 当前的 `tinkerpop.version` 为 `3.5.1`,其 `CypherAPI` 只接受 `@Consumes(APPLICATION_JSON)` +和原始 `String cypher` 请求体。测试栈使用 Java `17.0.20.1`、TinkerPop `3.8.1`、 +`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。 接口路径为 `/graphspaces/{graphspace}/graphs/{graph}/cypher`。一般用法见 [HugeGraph Cypher 指南](/cn/docs/language/hugegraph-cypher/)。 ### 请求形式与参数 -| 请求 | 已验证行为 | 测试方法 | -|---|---|---| -| `GET ?cypher=` | 保留原有查询参数形式 | `testGet` | -| `POST application/json`,请求体为原始 Cypher 文本 | 保留旧的原始文本请求形式 | `testPost` | -| `POST text/plain`,请求体为原始 Cypher 文本 | 支持纯文本请求 | `testPlainTextPost` | -| `POST application/json`,请求体为 JSON 对象 | 查询语句与参数分开传入 | `testParameters` | +| 请求 | 是否存在于已发布版本 | 测试栈上已验证行为 | 测试方法 | +|---|---|---|---| +| `GET ?cypher=` | 是 | 保留原有查询参数形式 | `testGet` | +| `POST application/json`,请求体为原始 Cypher 文本 | 是 | 保留旧的原始文本请求形式 | `testPost` | +| `POST text/plain`,请求体为原始 Cypher 文本 | 否 — 由 [#238](https://github.com/hugegraph/hugegraph/pull/238) 引入 | 支持纯文本请求 | `testPlainTextPost` | +| `POST application/json`,请求体为 JSON 对象 | 否 — 由 [#238](https://github.com/hugegraph/hugegraph/pull/238) 引入 | 查询语句与参数分开传入 | `testParameters` | + +因此下面的 JSON 对象形式**在任何已发布的 HugeGraph 版本中都不可用**,它只描述尚未合并的改动。 +在已发布版本上,引用 `$param` 的语句会把该参数绑定为 `null` 并返回空结果——参见 +[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 ```json { @@ -52,7 +64,8 @@ API 测试夹具使用强类型 Schema,并为 `city` 建立 `SECONDARY` 索引 `CypherApiTest` 通过 20/20,`CypherClientTest` 通过 7/7,`CypherOpProcessorTest` 通过 4/4,均无跳过。 相关 Gremlin 测试通过 10 项,另有一项 `testClearAndInit` 因后端不共享而不适用;Login 测试通过 3/3。 EditorConfig 格式检查和仓库根目录 clean compile 均通过。代码改动位于 -[PR #238](https://github.com/hugegraph/hugegraph/pull/238)。固定测试提交 +[PR #238](https://github.com/hugegraph/hugegraph/pull/238),该 PR **尚未合并**,基于贡献者 fork 的 +`task/tp381-3-upgrade-validation` 分支。固定测试提交 [`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md) 中的兼容性说明包含逐方法测试映射和验证记录。该提交的测试源码: [`CypherApiTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java)、 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index d236f056e1..7ef88a5a02 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -6,22 +6,36 @@ weight: 3 ### Scope +**No statement on this page describes a released HugeGraph version.** A released build exposes exactly two +request forms on `/graphspaces/{graphspace}/graphs/{graph}/cypher`: `GET ?cypher=` +and `POST application/json` with a raw Cypher body. Released versions accept no bound parameters, and a +statement that references `$param` returns no rows rather than failing — see +[Known limitations](/docs/language/hugegraph-cypher/#known-limitations). + This page records the cases verified for the current Cypher development change. It does not claim full openCypher or Neo4j compatibility, or compatibility across every released HugeGraph version. The tested -working tree is based on [`hugegraph/hugegraph@27a7c9b`](https://github.com/hugegraph/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf) -and uses Java `17.0.20.1`, TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. +working tree is based on +[`apache/hugegraph@27a7c9b`](https://github.com/apache/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf), +a TinkerPop 3.8 development commit that is **not an ancestor of `master`**: it has diverged, 10 commits +ahead and 5 behind. `master` currently declares `tinkerpop.version` `3.5.1` and its `CypherAPI` accepts +`@Consumes(APPLICATION_JSON)` with a raw `String cypher` body only. The tested tree used Java +`17.0.20.1`, TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage is covered in the [HugeGraph Cypher guide](/docs/language/hugegraph-cypher/). ### Request forms and parameters -| Request | Verified contract | Test method | -|---|---|---| -| `GET ?cypher=` | Existing query-string form | `testGet` | -| `POST application/json` with raw Cypher text | Legacy raw-body form remains available | `testPost` | -| `POST text/plain` with raw Cypher text | Plain-text form | `testPlainTextPost` | -| `POST application/json` with a JSON object | Query and bindings are sent separately | `testParameters` | +| Request | In a released version | Verified contract on the tested tree | Test method | +|---|---|---|---| +| `GET ?cypher=` | Yes | Existing query-string form | `testGet` | +| `POST application/json` with raw Cypher text | Yes | Legacy raw-body form remains available | `testPost` | +| `POST text/plain` with raw Cypher text | No — introduced by [#238](https://github.com/hugegraph/hugegraph/pull/238) | Plain-text form | `testPlainTextPost` | +| `POST application/json` with a JSON object | No — introduced by [#238](https://github.com/hugegraph/hugegraph/pull/238) | Query and bindings are sent separately | `testParameters` | + +The JSON object form below is therefore **not available in any released HugeGraph version**; it describes the +open change only. On released versions a statement using `$param` runs with that binding bound to `null` and +returns no rows — see [Known limitations](/docs/language/hugegraph-cypher/#known-limitations). ```json { @@ -55,7 +69,8 @@ Acceptance results are limited to these test cases: `CypherApiTest` passed 20/20, `CypherClientTest` 7/7, and `CypherOpProcessorTest` 4/4, with no skips. Related Gremlin tests passed 10 cases with one inapplicable `testClearAndInit` skip for a non-shared backend; Login tests passed 3/3. EditorConfig formatting and the repository-root clean compile passed. -The code change is in [PR #238](https://github.com/hugegraph/hugegraph/pull/238). The compatibility +The code change is in [PR #238](https://github.com/hugegraph/hugegraph/pull/238), which is **open and +unmerged**, based on the `task/tp381-3-upgrade-validation` branch of the contributor fork. The compatibility note at tested source commit [`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md) contains the method-level mapping and verification record. Test sources at that commit: [`CypherApiTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java), From f09e8e3ace9e75c59058aeae930e3088a013f0a4 Mon Sep 17 00:00:00 2001 From: n24q02m Date: Wed, 7 Oct 2026 08:08:34 +0700 Subject: [PATCH 08/17] docs: recommend SeaTunnel 3.0.0 for Neo4j migration (EN+CN) --- .../cn/docs/language/migrate-from-neo4j.md | 20 ++++++++++++-- .../en/docs/language/migrate-from-neo4j.md | 27 ++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/content/cn/docs/language/migrate-from-neo4j.md b/content/cn/docs/language/migrate-from-neo4j.md index 498c928da7..e2a6c4dd42 100644 --- a/content/cn/docs/language/migrate-from-neo4j.md +++ b/content/cn/docs/language/migrate-from-neo4j.md @@ -30,7 +30,7 @@ weight: 4 | 参数化查询 `$param` | 已发布版本仅发送原始语句 —— 缺失的绑定会被求值为 `null`(空结果),请在客户端校验取值;JSON 绑定参数随 [PR #238](https://github.com/hugegraph/hugegraph/pull/238) 落地 | | `CALL dbms.*` / `CALL algo.*` 过程 | 对应功能分散在 [traverser](/cn/docs/clients/restful-api/traverser/)、[task](/cn/docs/clients/restful-api/task/) 等 REST API | | 驱动:Neo4j Bolt driver | [hugegraph-client](/cn/docs/clients/hugegraph-client/)(`CypherManager`)或任意 HTTP 客户端 | -| 事务边界在 Cypher 语句内 | 每次请求一个语句;批量导入使用 [HugeGraph Loader](/cn/docs/quickstart/toolchain/hugegraph-loader/) | +| 事务边界在 Cypher 语句内 | 每次请求一个语句;图到图的数据迁移使用 [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/)(首选 —— 见下文),基于文件的批量导入使用 [HugeGraph Loader](/cn/docs/quickstart/toolchain/hugegraph-loader/) | ### 建议的迁移路径 @@ -39,8 +39,24 @@ weight: 4 "直接可用 / 需改写为 Gremlin / 需换 REST API" 三类。 2. **先建 schema**:用 schema API 建好 VertexLabel/EdgeLabel/PropertyKey 和索引 —— HugeGraph 在写入前要求 schema 存在。 -3. **导入数据**:小数据集用 REST;大批量用 +3. **导入数据**:首选路径是 [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/) + (2026-09-29 发布),直接运行 **Neo4j Source → HugeGraph Sink** —— 无需中间文件导出。 + 小数据集用 REST 也没问题;基于文件的大批量导入仍可使用 [HugeGraph Loader](https://github.com/apache/hugegraph-toolchain/tree/master/hugegraph-loader)。 + HugeGraph 侧的环境准备、`mappings` 配置与顶点/边导入示例见 + [通过 SeaTunnel Sink 导入图数据](/cn/docs/quickstart/toolchain/import/hugegraph-seatunnel-connector/)。 + + [SeaTunnel 3.0.0 连接器文档](https://seatunnel.apache.org/docs/3.0.0/about/) 说明了可依赖的能力: + - [Neo4j Source](https://seatunnel.apache.org/docs/3.0.0/connectors/source/Neo4j/) 以显式字段 + schema 读取 Cypher 查询结果;3.0.0 新增通过 `tables_configs` 的多表读取。 + - [HugeGraph Sink](https://seatunnel.apache.org/docs/3.0.0/connectors/sink/HugeGraph/) 在 3.0.0 + 中重构,支持多映射 —— 顶点/边请使用推荐的 `mappings` 配置,并遵循其 schema 创建行为。 + - [HugeGraph Source](https://seatunnel.apache.org/docs/3.0.0/connectors/source/HugeGraph/) 为 + 3.0.0 新增(schema 自动发现、多标签/并行读取),使 HugeGraph 的导出与迁移工作流成为可能。 + + 将 Neo4j 属性映射为 HugeGraph PropertyKey,保持稳定顶点 ID 不变,把边的端点映射到已存在的 + 顶点 ID,并先导入顶点、后导入边。以上能力均有文档记载,但这里没有完整跑通一次 Neo4j → + HugeGraph 迁移 —— 在把示例当作已验证之前,请先用你自己的数据验证。 4. **灰度切换**:Cypher 能表达的查询保持不动, translator 不支持的改写为 Gremlin(等价写法见 [对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法))。 diff --git a/content/en/docs/language/migrate-from-neo4j.md b/content/en/docs/language/migrate-from-neo4j.md index 6e2714c3a8..b40c551d60 100644 --- a/content/en/docs/language/migrate-from-neo4j.md +++ b/content/en/docs/language/migrate-from-neo4j.md @@ -31,7 +31,7 @@ verified and unverified areas and | Parameterized queries `$param` | Released versions send the raw statement only — a missing binding evaluates to `null` (empty result), so validate values client-side; JSON-bound parameters land in [PR #238](https://github.com/hugegraph/hugegraph/pull/238) | | `CALL dbms.*` / `CALL algo.*` procedures | Equivalent capabilities live in the [traverser](/docs/clients/restful-api/traverser/), [task](/docs/clients/restful-api/task/), and other REST APIs | | Driver: Neo4j Bolt driver | [hugegraph-client](/docs/clients/hugegraph-client/) (`CypherManager`) or any HTTP client | -| Transaction boundaries inside a Cypher statement | One statement per request; bulk imports use the [HugeGraph Loader](/docs/quickstart/toolchain/hugegraph-loader/) | +| Transaction boundaries inside a Cypher statement | One statement per request; graph-to-graph data migration uses [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/) (preferred — see below), file-based bulk loads use the [HugeGraph Loader](/docs/quickstart/toolchain/hugegraph-loader/) | ### Suggested migration path @@ -41,9 +41,30 @@ verified and unverified areas and 2. **Create the schema first**: define VertexLabel / EdgeLabel / PropertyKey and indexes through the schema API — HugeGraph requires the schema to exist before data is written. -3. **Import data**: REST for small datasets; the +3. **Import data**: the preferred path is + [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/) (released + 2026-09-29) running **Neo4j Source → HugeGraph Sink** directly — no + intermediate file export. REST remains fine for small datasets; the [HugeGraph Loader](https://github.com/apache/hugegraph-toolchain/tree/master/hugegraph-loader) - for bulk loads. + stays an alternative for file-based imports. HugeGraph-side setup + (environment, `mappings`, vertex/edge import examples) is covered in the + [Import Graph Data with SeaTunnel Sink guide](/docs/quickstart/toolchain/import/hugegraph-seatunnel-connector/). + + The [SeaTunnel 3.0.0 connector docs](https://seatunnel.apache.org/docs/3.0.0/about/) document + what to rely on: + - [Neo4j Source](https://seatunnel.apache.org/docs/3.0.0/connectors/source/Neo4j/) reads Cypher + query results with explicit field schemas; 3.0.0 adds multi-table reads via `tables_configs`. + - [HugeGraph Sink](https://seatunnel.apache.org/docs/3.0.0/connectors/sink/HugeGraph/) is + refactored in 3.0.0 with multi-mapping support — use the recommended `mappings` configuration + for vertices/edges and follow its schema-creation behavior. + - [HugeGraph Source](https://seatunnel.apache.org/docs/3.0.0/connectors/source/HugeGraph/) is + new in 3.0.0 (schema auto-discovery, multi-label/parallel reads), enabling HugeGraph export + and migration workflows. + + Map Neo4j properties to HugeGraph PropertyKeys, keep stable vertex IDs stable, map edge + endpoints to existing vertex IDs, and load vertices before edges. These capabilities are + documented, but a complete Neo4j → HugeGraph migration has not been run end-to-end here — + validate examples against your own data before treating them as tested. 4. **Switch incrementally**: keep the queries Cypher can express, and rewrite translator-unsupported constructs as Gremlin — the [equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents) From eb4e1aa24415cd0655c64d9b9dd5cfd12b39b74b Mon Sep 17 00:00:00 2001 From: imbajin Date: Thu, 8 Oct 2026 01:41:40 +0800 Subject: [PATCH 09/17] docs: align cypher verification with ASF master - link the standalone ASF change and tested source - document validated request and reserved value boundaries - refresh the bilingual verification record and regex scope - preserve the historical baseline failure evidence --- .../cn/docs/language/cypher-compatibility.md | 55 ++++++++++------- content/cn/docs/language/hugegraph-cypher.md | 4 +- .../en/docs/language/cypher-compatibility.md | 59 ++++++++++++------- content/en/docs/language/hugegraph-cypher.md | 4 +- 4 files changed, 74 insertions(+), 48 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index 214409e408..b09c8de602 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -12,12 +12,10 @@ weight: 3 不会报错,而是返回空结果——参见[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 本页记录当前 Cypher 开发改动实际验证过的用例,不代表完整支持 openCypher 或 Neo4j,也不代表所有已发布 -版本的 HugeGraph 都具备相同行为。测试代码基于 -[`apache/hugegraph@27a7c9b`](https://github.com/apache/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf), -这是一个 TinkerPop 3.8 开发提交,**不是 `master` 的祖先**:它已分叉,领先 10 个提交、落后 5 个提交。 -`master` 当前的 `tinkerpop.version` 为 `3.5.1`,其 `CypherAPI` 只接受 `@Consumes(APPLICATION_JSON)` -和原始 `String cypher` 请求体。测试栈使用 Java `17.0.20.1`、TinkerPop `3.8.1`、 -`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。 +版本的 HugeGraph 都具备相同行为。测试代码基于当前 Apache `master` 的 +[`e62c961`](https://github.com/apache/hugegraph/commit/e62c961e00221569d4f955abbadf60faee45b283), +该基线使用 Java 17 和 TinkerPop `3.8.1`。Cypher 改动独立建立在该基线上。运行栈使用 Java `17.0.20.1`、 +TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。 接口路径为 `/graphspaces/{graphspace}/graphs/{graph}/cypher`。一般用法见 [HugeGraph Cypher 指南](/cn/docs/language/hugegraph-cypher/)。 @@ -28,8 +26,8 @@ weight: 3 |---|---|---|---| | `GET ?cypher=` | 是 | 保留原有查询参数形式 | `testGet` | | `POST application/json`,请求体为原始 Cypher 文本 | 是 | 保留旧的原始文本请求形式 | `testPost` | -| `POST text/plain`,请求体为原始 Cypher 文本 | 否 — 由 [#238](https://github.com/hugegraph/hugegraph/pull/238) 引入 | 支持纯文本请求 | `testPlainTextPost` | -| `POST application/json`,请求体为 JSON 对象 | 否 — 由 [#238](https://github.com/hugegraph/hugegraph/pull/238) 引入 | 查询语句与参数分开传入 | `testParameters` | +| `POST text/plain`,任意请求体 | 否 | 返回 HTTP 415 | `testRejectPlainTextPost` | +| `POST application/json`,请求体为 JSON 对象 | 否 — 由 [#3289](https://github.com/apache/hugegraph/pull/3289) 引入 | 查询语句与参数分开传入 | `testParameters` | 因此下面的 JSON 对象形式**在任何已发布的 HugeGraph 版本中都不可用**,它只描述尚未合并的改动。 在已发布版本上,引用 `$param` 的语句会把该参数绑定为 `null` 并返回空结果——参见 @@ -42,9 +40,15 @@ weight: 3 } ``` +JSON 数组、字符串、数字、布尔值或 null 请求体会返回 HTTP 400。 +格式错误的 JSON 对象和尾随内容也会产生请求错误,不会回退为原始 Cypher 文本。 + JSON 对象中的 `cypher` 必须是非空字符串;`parameters` 若提供,必须是对象。省略 `parameters` 表示空参数表。 语句引用了未提供的参数时会报执行错误;显式传入 `null` 是有效值。测试覆盖字符串、数字、布尔值、引号和换行, 参数名 `id` 与 `label`,以及默认最多 16 个参数。参数值会作为绑定值传递,不会改写查询文本。 +转译库将精确字符串 `" cypher.null"`(开头有两个空格)保留为 null 标记,因此绑定值会拒绝该字符串, +包括列表和嵌套 Map 中的值。显式 null 仍受支持。语句字面量及存储属性等于该字符串的情况仍受转译库限制, +本次改动未验证这些值能够保真。 同时检查 HTTP 状态和响应体的 `status.code`:执行错误可能仍返回 HTTP 200,但 `status.code` 为 400,结果数据为 null。 @@ -54,28 +58,35 @@ API 测试夹具使用强类型 Schema,并为 `city` 建立 `SECONDARY` 索引 | 范围 | 测试用例 | 测试方法 | |---|---|---| -| 查询 | 标签扫描、相等和范围条件、布尔组合、有向一跳和两跳关系、空结果 | `testGet`、`testExactReadsAndPredicates`、`testRelationQuery` | +| 查询 | 标签扫描、相等和范围条件、布尔组合、有向一跳和两跳关系、空结果、计算字符串的正则全字符串匹配 | `testGet`、`testExactReadsAndPredicates`、`testRelationQuery`、`testComputedRegexExecutesExtensionPredicate`、`testComputedRegexRequiresWholeStringMatch` | | 结果 | 别名、标量和节点值、嵌套值、关系 ID、路径结构、null 与缺失属性 | `testReturnNodeIdAsPrimitiveValue`、`testReturnNodeDoesNotLeakInternalIdTypes`、`testReturnNestedIdDoesNotLeakInternalIdTypes`、`testReturnRelationIdDoesNotLeakInternalIdTypes`、`testReturnPathShape`、`testNullAndMissingProperty` | | 聚合和分页 | `DISTINCT`、`count`/`sum`/`min`/`max`/`avg`、`ORDER BY`、`SKIP`、`LIMIT` | `testDuplicatesDistinctAndPagination`、`testAggregates` | | 写入 | 创建顶点和边、修改属性、删除边和顶点;通过原生 REST 读取检查状态 | `testCreate`、`testCreateSetAndDeleteWithNativeReadback` | | 失败写入 | 拒绝双顶点 `CREATE` 后,连续 32 次查询和原生读取均未发现残留 | `testFailedWriteDoesNotLeakIntoLaterRequests` | -| 错误与路由 | 非法语法和请求结构、参数键、Schema 值、认证及图路由 | `testInvalidRequests`、`testRejectInvalidQuery`、`testRejectInvalidBindingShapeAndKeys`、`testAuthenticationAndGraphRouting`、`testSpecifiedGraphRouting` | - -`CypherApiTest` 通过 20/20,`CypherClientTest` 通过 7/7,`CypherOpProcessorTest` 通过 4/4,均无跳过。 -相关 Gremlin 测试通过 10 项,另有一项 `testClearAndInit` 因后端不共享而不适用;Login 测试通过 3/3。 -EditorConfig 格式检查和仓库根目录 clean compile 均通过。代码改动位于 -[PR #238](https://github.com/hugegraph/hugegraph/pull/238),该 PR **尚未合并**,基于贡献者 fork 的 -`task/tp381-3-upgrade-validation` 分支。固定测试提交 -[`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md) -中的兼容性说明包含逐方法测试映射和验证记录。该提交的测试源码: -[`CypherApiTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java)、 -[`CypherClientTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java) +| 错误与路由 | 非法语法和请求结构、内容类型、参数键与保留的 null 标记、Schema 值、认证及图路由 | `testInvalidRequests`、`testRejectPlainTextPost`、`testRejectInvalidQuery`、`testRejectInvalidBindingShapeAndKeys`、`testRejectTranslatorNullMarker`、`testRejectTranslatorNullSentinelInBindings`、`testAuthenticationAndGraphRouting`、`testSpecifiedGraphRouting` | + +独立代码改动位于 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289),该 PR 尚未合并,已变基到上述 Apache `master` 基线。 +原始开发改动仍关联 [PR #238](https://github.com/hugegraph/hugegraph/pull/238)。 +在固定源码提交 +[`fd8f4a6`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/docs/cypher-compatibility.md) 上,`CypherApiTest` 通过 23/23, +`CypherClientTest` 通过 7/7,`CypherOpProcessorTest` 通过 8/8,均无跳过。新增的谓词、执行上下文和请求资源所有权 +回归测试均通过;`AbstractRestClientTest` 的九项测试也全部通过,包括 ASCII 请求体、UTF-16 Map 请求体及 gzip。 +Login 测试通过 3/3;相关 Gremlin 测试通过 10 项,保留一项因后端不共享而不适用的 `testClearAndInit` 跳过。 +EditorConfig 格式检查、仓库根目录 clean compile 和完整 install 均通过。在实际服务测试前,分发包内的 API JAR 与编译目标 JAR 一致。 + +该固定提交中的兼容性说明包含验证记录和逐方法映射。测试源码: +[`CypherApiTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java)、 +[`CypherClientTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java) 和 -[`CypherOpProcessorTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java)。 +[`CypherOpProcessorTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java)。 +此前变基前的验证记录仍保留在 +[`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md)。 ### 基线故障与当前修复 -在上述固定基线提交中,失败的双顶点 `CREATE` 在两次观察中都留下了延迟可见的残留。第一次运行中,即时原生读取未发现前缀, +在此前的基线 +[`27a7c9b`](https://github.com/apache/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf) +中,失败的双顶点 `CREATE` 在两次观察中都留下了延迟可见的残留。第一次运行中,即时原生读取未发现前缀, 但后续聚合/排序查询暴露了前缀,原生全量列表也确认了它。第二次复现时,即时原生读取和之后 7 次 count/原生读取均未见前缀; 第 8 次 count 后才出现。原始基线证据保留在 [基线报告](https://github.com/apache/hugegraph-doc/pull/499#issuecomment-5826172378)。 diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index a77c64bd9e..4be227ea23 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -136,8 +136,8 @@ MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代的工具链。已知缺口: -- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被求值为 `null`,查询返回空结果(或写入 null 值)。请在客户端先对值做转义/净化再拼接到语句中。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)将随 [PR #238](https://github.com/hugegraph/hugegraph/pull/238) 落地。 -- **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`=~` 正则谓词、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 +- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被求值为 `null`,查询返回空结果(或写入 null 值)。请在客户端先对值做转义/净化再拼接到语句中。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)由尚未合并的 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 提议引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 +- **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证。开发改动验证了计算字符串上的两个 `=~` 全字符串匹配用例,更广泛的正则覆盖仍未验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 - **不支持 `CALL` 过程** —— HugeGraph 的图算法(最短路径、k-out、personalrank 等)未暴露为 Cypher 过程;请改用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin。 - **每次请求仅一条语句** —— 不支持多语句脚本,请每次调用发送一条语句。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index 7ef88a5a02..8aa9788908 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -14,12 +14,10 @@ statement that references `$param` returns no rows rather than failing — see This page records the cases verified for the current Cypher development change. It does not claim full openCypher or Neo4j compatibility, or compatibility across every released HugeGraph version. The tested -working tree is based on -[`apache/hugegraph@27a7c9b`](https://github.com/apache/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf), -a TinkerPop 3.8 development commit that is **not an ancestor of `master`**: it has diverged, 10 commits -ahead and 5 behind. `master` currently declares `tinkerpop.version` `3.5.1` and its `CypherAPI` accepts -`@Consumes(APPLICATION_JSON)` with a raw `String cypher` body only. The tested tree used Java -`17.0.20.1`, TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. +working tree is based on current Apache `master` at +[`e62c961`](https://github.com/apache/hugegraph/commit/e62c961e00221569d4f955abbadf60faee45b283), +which uses Java 17 and TinkerPop `3.8.1`. This is a standalone Cypher change on that baseline. The runtime +uses Java `17.0.20.1`, TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage is covered in the [HugeGraph Cypher guide](/docs/language/hugegraph-cypher/). @@ -30,8 +28,8 @@ The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage |---|---|---|---| | `GET ?cypher=` | Yes | Existing query-string form | `testGet` | | `POST application/json` with raw Cypher text | Yes | Legacy raw-body form remains available | `testPost` | -| `POST text/plain` with raw Cypher text | No — introduced by [#238](https://github.com/hugegraph/hugegraph/pull/238) | Plain-text form | `testPlainTextPost` | -| `POST application/json` with a JSON object | No — introduced by [#238](https://github.com/hugegraph/hugegraph/pull/238) | Query and bindings are sent separately | `testParameters` | +| `POST text/plain` with any body | No | Rejected with HTTP 415 | `testRejectPlainTextPost` | +| `POST application/json` with a JSON object | No — introduced by [#3289](https://github.com/apache/hugegraph/pull/3289) | Query and bindings are sent separately | `testParameters` | The JSON object form below is therefore **not available in any released HugeGraph version**; it describes the open change only. On released versions a statement using `$param` runs with that binding bound to `null` and @@ -44,10 +42,17 @@ returns no rows — see [Known limitations](/docs/language/hugegraph-cypher/#kno } ``` +POST bodies containing JSON arrays, strings, numbers, booleans, or null are rejected with HTTP 400. +Malformed JSON objects and trailing tokens also produce request errors; they do not fall back to raw Cypher. + For the JSON-object form, `cypher` must be a nonblank string and `parameters`, if present, must be an object. Omitting `parameters` means an empty map. A referenced but missing binding is an execution error; an explicit null value is valid. Tests cover string, number, and boolean values, quotes and newlines, the binding names `id` and `label`, and the default limit of 16 parameters. Values remain bindings and do not alter query text. +The translator reserves the exact string `" cypher.null"` (two leading spaces) as its null marker. That +string is rejected as a binding value, including inside lists and nested maps. Explicit null remains +supported. Literal query values and stored properties equal to that string remain a translator limitation; +this change does not establish value preservation for those cases. Check both the HTTP status and the response body's `status.code`: an execution failure can retain HTTP 200 while returning `status.code` 400 and null result data. @@ -59,27 +64,37 @@ Acceptance results are limited to these test cases: | Area | Tested cases | Test methods | |---|---|---| -| Reads | Label scans; equality and range predicates; boolean combinations; directed one- and two-hop patterns; empty results | `testGet`, `testExactReadsAndPredicates`, `testRelationQuery` | +| Reads | Label scans; equality and range predicates; boolean combinations; directed one- and two-hop patterns; empty results; whole-string regex matching on computed strings | `testGet`, `testExactReadsAndPredicates`, `testRelationQuery`, `testComputedRegexExecutesExtensionPredicate`, `testComputedRegexRequiresWholeStringMatch` | | Results | Aliases, scalar and node values, nested values, relationship ids, path shape, null and missing properties | `testReturnNodeIdAsPrimitiveValue`, `testReturnNodeDoesNotLeakInternalIdTypes`, `testReturnNestedIdDoesNotLeakInternalIdTypes`, `testReturnRelationIdDoesNotLeakInternalIdTypes`, `testReturnPathShape`, `testNullAndMissingProperty` | | Aggregation and pagination | `DISTINCT`, `count`/`sum`/`min`/`max`/`avg`, `ORDER BY`, `SKIP`, and `LIMIT` | `testDuplicatesDistinctAndPagination`, `testAggregates` | | Writes | Vertex and edge `CREATE`, property `SET`, edge and vertex `DELETE`; state checked through native REST reads | `testCreate`, `testCreateSetAndDeleteWithNativeReadback` | | Failed write | A rejected two-vertex `CREATE` left no residue during 32 subsequent query and native-read checks | `testFailedWriteDoesNotLeakIntoLaterRequests` | -| Errors and routing | Invalid syntax and request shape, binding keys, schema values, authentication, and graph routing | `testInvalidRequests`, `testRejectInvalidQuery`, `testRejectInvalidBindingShapeAndKeys`, `testAuthenticationAndGraphRouting`, `testSpecifiedGraphRouting` | - -`CypherApiTest` passed 20/20, `CypherClientTest` 7/7, and `CypherOpProcessorTest` 4/4, with no skips. -Related Gremlin tests passed 10 cases with one inapplicable `testClearAndInit` skip for a non-shared backend; -Login tests passed 3/3. EditorConfig formatting and the repository-root clean compile passed. -The code change is in [PR #238](https://github.com/hugegraph/hugegraph/pull/238), which is **open and -unmerged**, based on the `task/tp381-3-upgrade-validation` branch of the contributor fork. The compatibility -note at tested source commit [`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md) -contains the method-level mapping and verification record. Test sources at that commit: -[`CypherApiTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java), -[`CypherClientTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java), -and [`CypherOpProcessorTest`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java). +| Errors and routing | Invalid syntax and request shape, content type, binding keys and the reserved null marker, schema values, authentication, and graph routing | `testInvalidRequests`, `testRejectPlainTextPost`, `testRejectInvalidQuery`, `testRejectInvalidBindingShapeAndKeys`, `testRejectTranslatorNullMarker`, `testRejectTranslatorNullSentinelInBindings`, `testAuthenticationAndGraphRouting`, `testSpecifiedGraphRouting` | + +The standalone code change is in [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), +which is open and unmerged, rebased onto the Apache `master` baseline above. The original development +change remains linked in [PR #238](https://github.com/hugegraph/hugegraph/pull/238). At source commit +[`fd8f4a6`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/docs/cypher-compatibility.md), `CypherApiTest` passed 23/23, +`CypherClientTest` 7/7, and `CypherOpProcessorTest` 8/8, with no skips. The additional predicate, +execution-context, and request-ownership regressions passed, as did all nine `AbstractRestClientTest` +cases, including ASCII and UTF-16 map bodies with gzip. Login tests passed 3/3; related Gremlin tests +passed 10 cases with one existing, inapplicable `testClearAndInit` skip for a non-shared backend. +EditorConfig formatting, the repository-root clean compile, and the full install passed. The packaged +API JAR matched the compiled target JAR before the live test run. + +The compatibility note at that fixed commit contains the verification record and method-level mapping. +Test sources: +[`CypherApiTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java), +[`CypherClientTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java), +and [`CypherOpProcessorTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java). +The earlier, pre-rebase verification remains at +[`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md). ### Baseline failure and current fix -At the pinned baseline commit above, a failed two-vertex `CREATE` left delayed residue in two observations. +At the earlier baseline +[`27a7c9b`](https://github.com/apache/hugegraph/commit/27a7c9b42274d6d4f95eabed6d2051d393ae0eaf), +a failed two-vertex `CREATE` left delayed residue in two observations. In the first run, an immediate native read missed the prefix, but later aggregate/sort reads exposed it and a full native listing confirmed it. In the second reproduction, immediate native reads and seven later count/native-read checks showed no prefix; it appeared after the eighth count. The original baseline evidence remains in diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index b579cbf042..8daf325bfd 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -136,8 +136,8 @@ Tip: `EXPLAIN MATCH (n:person) RETURN n` is parsed with the `EXPLAIN` option, an Cypher support in HugeGraph is bounded by the transpiler layer, which is based on openCypher 9 era tooling. Known gaps: -- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding evaluates to `null`, so the query returns no rows (or writes null values) rather than failing. Sanitize/escape values on the client side before interpolating them into the statement. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are on the way in [PR #238](https://github.com/hugegraph/hugegraph/pull/238). -- **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET`, `=~` regex predicates, and `NOT ... IN` do translate, but they are not verified end-to-end on HugeGraph — see the [compatibility notes](/docs/language/cypher-compatibility/). +- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding evaluates to `null`, so the query returns no rows (or writes null values) rather than failing. Sanitize/escape values on the client side before interpolating them into the statement. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are proposed in the unmerged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. +- **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET` and `NOT ... IN` do translate, but they are not verified end-to-end on HugeGraph. The development change verifies two whole-string `=~` matching cases on computed strings; broader regex coverage remains unverified — see the [compatibility notes](/docs/language/cypher-compatibility/). - **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. - **Single statement per request** — multi-statement scripts are not supported; send one statement per call. From 486f137df4627ebe05f0146cd8fd3f7f8a2861f7 Mon Sep 17 00:00:00 2001 From: imbajin Date: Thu, 8 Oct 2026 20:51:35 +0800 Subject: [PATCH 10/17] docs: clarify the fixed cypher binding limit - document the fixed top-level parameter cap - show verified explicit map field references - refresh source pins after the master rebase --- .../cn/docs/language/cypher-compatibility.md | 34 ++++++++++++---- .../en/docs/language/cypher-compatibility.md | 39 +++++++++++++++---- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index b09c8de602..ec7c86259d 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -13,8 +13,8 @@ weight: 3 本页记录当前 Cypher 开发改动实际验证过的用例,不代表完整支持 openCypher 或 Neo4j,也不代表所有已发布 版本的 HugeGraph 都具备相同行为。测试代码基于当前 Apache `master` 的 -[`e62c961`](https://github.com/apache/hugegraph/commit/e62c961e00221569d4f955abbadf60faee45b283), -该基线使用 Java 17 和 TinkerPop `3.8.1`。Cypher 改动独立建立在该基线上。运行栈使用 Java `17.0.20.1`、 +[`af3c686`](https://github.com/apache/hugegraph/commit/af3c6867f4bfa3f95e63ad472c12a88c63529c1b), +该基线声明 HugeGraph `1.8.0`,使用 Java 17 和 TinkerPop `3.8.1`。Cypher 改动独立建立在该基线上。运行栈使用 Java `17.0.20.1`、 TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。 接口路径为 `/graphspaces/{graphspace}/graphs/{graph}/cypher`。一般用法见 @@ -45,7 +45,23 @@ JSON 数组、字符串、数字、布尔值或 null 请求体会返回 HTTP 400 JSON 对象中的 `cypher` 必须是非空字符串;`parameters` 若提供,必须是对象。省略 `parameters` 表示空参数表。 语句引用了未提供的参数时会报执行错误;显式传入 `null` 是有效值。测试覆盖字符串、数字、布尔值、引号和换行, -参数名 `id` 与 `label`,以及默认最多 16 个参数。参数值会作为绑定值传递,不会改写查询文本。 +参数名 `id` 与 `label`。当前实现的 `parameters` 最多接受 16 个顶层条目,该上限固定。 +该上限只统计顶层 `parameters` 对象中的键。Cypher 不支持在 Gremlin Server 的处理器配置中设置 +`maxParameters`。参数值会作为绑定值传递,不会改写查询文本。 + +一个 Map 只计为一个顶层参数。可以将相关值放入一个 Map,并显式引用各字段;顶点标签和必需属性必须匹配图中已有的 Schema: + +```json +{ + "cypher": "CREATE (n:cypher_person {name:$props.name, age:$props.age, city:$props.city}) RETURN n.name", + "parameters": {"props": {"name": "new-person", "age": 20, "city": "Beijing"}} +} +``` + +实际 REST 验证确认,一个包含 17 个条目的 Map 可以通过显式属性引用完成写入,并通过原生 REST 核对全部 17 个持久化值。 +返回包含 17 个条目的 Map 也成功,而 17 个顶层绑定参数会产生执行错误。请使用上述显式属性引用; +固定版本的转译库不会通过 CREATE 的简写形式赋予绑定 Map 中的属性。 + 转译库将精确字符串 `" cypher.null"`(开头有两个空格)保留为 null 标记,因此绑定值会拒绝该字符串, 包括列表和嵌套 Map 中的值。显式 null 仍受支持。语句字面量及存储属性等于该字符串的情况仍受转译库限制, 本次改动未验证这些值能够保真。 @@ -68,17 +84,21 @@ API 测试夹具使用强类型 Schema,并为 `city` 建立 `SECONDARY` 索引 独立代码改动位于 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289),该 PR 尚未合并,已变基到上述 Apache `master` 基线。 原始开发改动仍关联 [PR #238](https://github.com/hugegraph/hugegraph/pull/238)。 在固定源码提交 -[`fd8f4a6`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/docs/cypher-compatibility.md) 上,`CypherApiTest` 通过 23/23, +[`8d06ad3`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/docs/cypher-compatibility.md) 上,`CypherApiTest` 通过 23/23, `CypherClientTest` 通过 7/7,`CypherOpProcessorTest` 通过 8/8,均无跳过。新增的谓词、执行上下文和请求资源所有权 回归测试均通过;`AbstractRestClientTest` 的九项测试也全部通过,包括 ASCII 请求体、UTF-16 Map 请求体及 gzip。 Login 测试通过 3/3;相关 Gremlin 测试通过 10 项,保留一项因后端不共享而不适用的 `testClearAndInit` 跳过。 EditorConfig 格式检查、仓库根目录 clean compile 和完整 install 均通过。在实际服务测试前,分发包内的 API JAR 与编译目标 JAR 一致。 该固定提交中的兼容性说明包含验证记录和逐方法映射。测试源码: -[`CypherApiTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java)、 -[`CypherClientTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java) +[`CypherApiTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java)、 +[`CypherClientTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java) 和 -[`CypherOpProcessorTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java)。 +[`CypherOpProcessorTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java)。 +此前在 +[`e62c961`](https://github.com/apache/hugegraph/commit/e62c961e00221569d4f955abbadf60faee45b283) +基线上的验证仍保留在 +[`fd8f4a6`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/docs/cypher-compatibility.md)。 此前变基前的验证记录仍保留在 [`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md)。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index 8aa9788908..26b2db7b8d 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -15,9 +15,9 @@ statement that references `$param` returns no rows rather than failing — see This page records the cases verified for the current Cypher development change. It does not claim full openCypher or Neo4j compatibility, or compatibility across every released HugeGraph version. The tested working tree is based on current Apache `master` at -[`e62c961`](https://github.com/apache/hugegraph/commit/e62c961e00221569d4f955abbadf60faee45b283), -which uses Java 17 and TinkerPop `3.8.1`. This is a standalone Cypher change on that baseline. The runtime -uses Java `17.0.20.1`, TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. +[`af3c686`](https://github.com/apache/hugegraph/commit/af3c6867f4bfa3f95e63ad472c12a88c63529c1b), +which declares HugeGraph `1.8.0`, Java 17, and TinkerPop `3.8.1`. This is a standalone Cypher change on that +baseline. The runtime uses Java `17.0.20.1`, TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage is covered in the [HugeGraph Cypher guide](/docs/language/hugegraph-cypher/). @@ -48,7 +48,26 @@ Malformed JSON objects and trailing tokens also produce request errors; they do For the JSON-object form, `cypher` must be a nonblank string and `parameters`, if present, must be an object. Omitting `parameters` means an empty map. A referenced but missing binding is an execution error; an explicit null value is valid. Tests cover string, number, and boolean values, quotes and newlines, the binding names -`id` and `label`, and the default limit of 16 parameters. Values remain bindings and do not alter query text. +`id` and `label`. The current implementation accepts at most 16 top-level entries in `parameters`; this +limit is fixed. Only keys in the top-level `parameters` object count toward it. Cypher does not support a +`maxParameters` setting in Gremlin Server's processor configuration. Values remain bindings and do not +alter query text. + +A Map counts as one top-level parameter. Group related values into one Map and reference its fields +explicitly; the vertex label and required properties must match the graph's existing schema: + +```json +{ + "cypher": "CREATE (n:cypher_person {name:$props.name, age:$props.age, city:$props.city}) RETURN n.name", + "parameters": {"props": {"name": "new-person", "age": 20, "city": "Beijing"}} +} +``` + +Live REST verification confirmed that one Map containing 17 entries works with explicit property +references, with all 17 persisted values checked through native REST. A 17-entry returned Map also +succeeds, while 17 top-level bindings produce an execution error. Use the explicit property references +shown above; the pinned translator does not assign a bound Map's fields through the shorthand CREATE form. + The translator reserves the exact string `" cypher.null"` (two leading spaces) as its null marker. That string is rejected as a binding value, including inside lists and nested maps. Explicit null remains supported. Literal query values and stored properties equal to that string remain a translator limitation; @@ -74,7 +93,7 @@ Acceptance results are limited to these test cases: The standalone code change is in [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), which is open and unmerged, rebased onto the Apache `master` baseline above. The original development change remains linked in [PR #238](https://github.com/hugegraph/hugegraph/pull/238). At source commit -[`fd8f4a6`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/docs/cypher-compatibility.md), `CypherApiTest` passed 23/23, +[`8d06ad3`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/docs/cypher-compatibility.md), `CypherApiTest` passed 23/23, `CypherClientTest` 7/7, and `CypherOpProcessorTest` 8/8, with no skips. The additional predicate, execution-context, and request-ownership regressions passed, as did all nine `AbstractRestClientTest` cases, including ASCII and UTF-16 map bodies with gzip. Login tests passed 3/3; related Gremlin tests @@ -84,9 +103,13 @@ API JAR matched the compiled target JAR before the live test run. The compatibility note at that fixed commit contains the verification record and method-level mapping. Test sources: -[`CypherApiTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java), -[`CypherClientTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java), -and [`CypherOpProcessorTest`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java). +[`CypherApiTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java), +[`CypherClientTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java), +and [`CypherOpProcessorTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java). +The earlier verification on +[`e62c961`](https://github.com/apache/hugegraph/commit/e62c961e00221569d4f955abbadf60faee45b283) +remains at +[`fd8f4a6`](https://github.com/apache/hugegraph/blob/fd8f4a626b9e899663d3114035e2967e421b3e55/docs/cypher-compatibility.md). The earlier, pre-rebase verification remains at [`c3b2f3e`](https://github.com/hugegraph/hugegraph/blob/c3b2f3e3b9ff1de0495260d6eec0b16816d7f095/docs/cypher-compatibility.md). From 38db01d9ddd086729c5890df882a722b5e6b34ef Mon Sep 17 00:00:00 2001 From: imbajin Date: Fri, 9 Oct 2026 00:31:50 +0800 Subject: [PATCH 11/17] docs: reflect merged cypher parameter support - mark the upstream Cypher change as merged - distinguish master support from the 1.7.0 release - align bilingual usage and migration notes - separate translator TCK results from compatibility claims --- content/cn/docs/language/cypher-compatibility.md | 7 ++++--- content/cn/docs/language/hugegraph-cypher.md | 4 +++- content/cn/docs/language/migrate-from-neo4j.md | 6 +++++- content/en/docs/language/cypher-compatibility.md | 9 +++++---- content/en/docs/language/hugegraph-cypher.md | 4 +++- content/en/docs/language/migrate-from-neo4j.md | 7 ++++++- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index ec7c86259d..ecb365d910 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -6,7 +6,7 @@ weight: 3 ### 范围 -**本页没有任何描述适用于已发布的 HugeGraph 版本。** 已发布版本在 +**下文验证结果描述的是 `master`,不能直接套用于已发布版本。** 已发布版本在 `/graphspaces/{graphspace}/graphs/{graph}/cypher` 上只提供两种请求形式:`GET ?cypher=` 和 `POST application/json`(请求体为原始 Cypher 文本)。已发布版本不接受绑定参数,引用 `$param` 的语句 不会报错,而是返回空结果——参见[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 @@ -29,7 +29,7 @@ TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。 | `POST text/plain`,任意请求体 | 否 | 返回 HTTP 415 | `testRejectPlainTextPost` | | `POST application/json`,请求体为 JSON 对象 | 否 — 由 [#3289](https://github.com/apache/hugegraph/pull/3289) 引入 | 查询语句与参数分开传入 | `testParameters` | -因此下面的 JSON 对象形式**在任何已发布的 HugeGraph 版本中都不可用**,它只描述尚未合并的改动。 +因此下面的 JSON 对象形式**在任何已发布的 HugeGraph 版本中都不可用**,它描述已合入 `master`(1.8.0 开发线)的改动。 在已发布版本上,引用 `$param` 的语句会把该参数绑定为 `null` 并返回空结果——参见 [已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 @@ -81,7 +81,8 @@ API 测试夹具使用强类型 Schema,并为 `city` 建立 `SECONDARY` 索引 | 失败写入 | 拒绝双顶点 `CREATE` 后,连续 32 次查询和原生读取均未发现残留 | `testFailedWriteDoesNotLeakIntoLaterRequests` | | 错误与路由 | 非法语法和请求结构、内容类型、参数键与保留的 null 标记、Schema 值、认证及图路由 | `testInvalidRequests`、`testRejectPlainTextPost`、`testRejectInvalidQuery`、`testRejectInvalidBindingShapeAndKeys`、`testRejectTranslatorNullMarker`、`testRejectTranslatorNullSentinelInBindings`、`testAuthenticationAndGraphRouting`、`testSpecifiedGraphRouting` | -独立代码改动位于 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289),该 PR 尚未合并,已变基到上述 Apache `master` 基线。 +独立代码改动位于 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289),该 PR 已于 2026-10-08 合入 Apache `master`,合入提交为 +[`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb)。上述固定基线仍对应合入前的实际验证。 原始开发改动仍关联 [PR #238](https://github.com/hugegraph/hugegraph/pull/238)。 在固定源码提交 [`8d06ad3`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/docs/cypher-compatibility.md) 上,`CypherApiTest` 通过 23/23, diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index 4be227ea23..9cda8ceecd 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -136,7 +136,7 @@ MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代的工具链。已知缺口: -- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被求值为 `null`,查询返回空结果(或写入 null 值)。请在客户端先对值做转义/净化再拼接到语句中。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)由尚未合并的 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 提议引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 +- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被求值为 `null`,查询返回空结果(或写入 null 值)。请在客户端先对值做转义/净化再拼接到语句中。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)已通过合入 `master` 的 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 - **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证。开发改动验证了计算字符串上的两个 `=~` 全字符串匹配用例,更广泛的正则覆盖仍未验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 - **不支持 `CALL` 过程** —— HugeGraph 的图算法(最短路径、k-out、personalrank 等)未暴露为 Cypher 过程;请改用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin。 - **每次请求仅一条语句** —— 不支持多语句脚本,请每次调用发送一条语句。 @@ -148,3 +148,5 @@ HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代 - [Cypher REST API 参考](/cn/docs/clients/restful-api/cypher/) - [Gremlin 查询语言](/cn/docs/language/hugegraph-gremlin/) - [openCypher 项目](https://opencypher.org/) —— 语言规范与资源 + +转译库历史 TCK 通过比例不等于 HugeGraph 端到端兼容率;本页没有给出经测量的 HugeGraph Cypher 总体兼容百分比。 diff --git a/content/cn/docs/language/migrate-from-neo4j.md b/content/cn/docs/language/migrate-from-neo4j.md index e2a6c4dd42..8b67f772b6 100644 --- a/content/cn/docs/language/migrate-from-neo4j.md +++ b/content/cn/docs/language/migrate-from-neo4j.md @@ -27,11 +27,13 @@ weight: 4 |---|---| | `CREATE INDEX` / `CREATE CONSTRAINT` | 通过 [schema REST API](/cn/docs/clients/restful-api/schema/) 建索引/约束;Cypher 不承载 DDL | | 隐式 schema(属性随意添加) | **强 schema**:先定义 VertexLabel/EdgeLabel/PropertyKey,再写数据 | -| 参数化查询 `$param` | 已发布版本仅发送原始语句 —— 缺失的绑定会被求值为 `null`(空结果),请在客户端校验取值;JSON 绑定参数随 [PR #238](https://github.com/hugegraph/hugegraph/pull/238) 落地 | +| 参数化查询 `$param` | 已发布版本仅发送原始语句 —— 缺失的绑定会被求值为 `null`(空结果),请在客户端校验取值;JSON 绑定参数已通过 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 合入 `master`,固定最多 16 个顶层绑定参数 | | `CALL dbms.*` / `CALL algo.*` 过程 | 对应功能分散在 [traverser](/cn/docs/clients/restful-api/traverser/)、[task](/cn/docs/clients/restful-api/task/) 等 REST API | | 驱动:Neo4j Bolt driver | [hugegraph-client](/cn/docs/clients/hugegraph-client/)(`CypherManager`)或任意 HTTP 客户端 | | 事务边界在 Cypher 语句内 | 每次请求一个语句;图到图的数据迁移使用 [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/)(首选 —— 见下文),基于文件的批量导入使用 [HugeGraph Loader](/cn/docs/quickstart/toolchain/hugegraph-loader/) | +截至 2026-10-09,最新已发布版本为 1.7.0;JSON 绑定请求已进入 `master`(1.8.0 开发线),不能据此认为 1.7.0 已支持。 + ### 建议的迁移路径 1. **盘点查询**:把应用里的 Cypher 按 @@ -69,3 +71,5 @@ weight: 4 - 不受支持的查询结构通常可以改写为等价的 Gremlin 遍历 —— 见 [HugeGraph Cypher 的对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法); schema DDL 与 `CALL` 过程请改用 REST API。 + +转译库历史 TCK 通过比例不等于 HugeGraph 端到端兼容率;本页没有给出经测量的 HugeGraph Cypher 总体兼容百分比。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index 26b2db7b8d..025820683e 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -6,7 +6,7 @@ weight: 3 ### Scope -**No statement on this page describes a released HugeGraph version.** A released build exposes exactly two +**The verification results below describe `master`, not a released HugeGraph version.** A released build exposes exactly two request forms on `/graphspaces/{graphspace}/graphs/{graph}/cypher`: `GET ?cypher=` and `POST application/json` with a raw Cypher body. Released versions accept no bound parameters, and a statement that references `$param` returns no rows rather than failing — see @@ -31,8 +31,7 @@ The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage | `POST text/plain` with any body | No | Rejected with HTTP 415 | `testRejectPlainTextPost` | | `POST application/json` with a JSON object | No — introduced by [#3289](https://github.com/apache/hugegraph/pull/3289) | Query and bindings are sent separately | `testParameters` | -The JSON object form below is therefore **not available in any released HugeGraph version**; it describes the -open change only. On released versions a statement using `$param` runs with that binding bound to `null` and +The JSON object form below is therefore **not available in any released HugeGraph version**; it describes the merged change on `master` (the 1.8.0 development line). On released versions a statement using `$param` runs with that binding bound to `null` and returns no rows — see [Known limitations](/docs/language/hugegraph-cypher/#known-limitations). ```json @@ -91,7 +90,9 @@ Acceptance results are limited to these test cases: | Errors and routing | Invalid syntax and request shape, content type, binding keys and the reserved null marker, schema values, authentication, and graph routing | `testInvalidRequests`, `testRejectPlainTextPost`, `testRejectInvalidQuery`, `testRejectInvalidBindingShapeAndKeys`, `testRejectTranslatorNullMarker`, `testRejectTranslatorNullSentinelInBindings`, `testAuthenticationAndGraphRouting`, `testSpecifiedGraphRouting` | The standalone code change is in [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), -which is open and unmerged, rebased onto the Apache `master` baseline above. The original development +which was merged into Apache `master` on 2026-10-08 as +[`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb). +The verified pre-merge baseline remains pinned above. The original development change remains linked in [PR #238](https://github.com/hugegraph/hugegraph/pull/238). At source commit [`8d06ad3`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/docs/cypher-compatibility.md), `CypherApiTest` passed 23/23, `CypherClientTest` 7/7, and `CypherOpProcessorTest` 8/8, with no skips. The additional predicate, diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index 8daf325bfd..38f32bf7c5 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -136,7 +136,7 @@ Tip: `EXPLAIN MATCH (n:person) RETURN n` is parsed with the `EXPLAIN` option, an Cypher support in HugeGraph is bounded by the transpiler layer, which is based on openCypher 9 era tooling. Known gaps: -- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding evaluates to `null`, so the query returns no rows (or writes null values) rather than failing. Sanitize/escape values on the client side before interpolating them into the statement. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are proposed in the unmerged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. +- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding evaluates to `null`, so the query returns no rows (or writes null values) rather than failing. Sanitize/escape values on the client side before interpolating them into the statement. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. - **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET` and `NOT ... IN` do translate, but they are not verified end-to-end on HugeGraph. The development change verifies two whole-string `=~` matching cases on computed strings; broader regex coverage remains unverified — see the [compatibility notes](/docs/language/cypher-compatibility/). - **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. - **Single statement per request** — multi-statement scripts are not supported; send one statement per call. @@ -148,3 +148,5 @@ When a statement fails translation, the response `status.message` contains the t - [Cypher REST API reference](/docs/clients/restful-api/cypher/) - [Gremlin Query Language](/docs/language/hugegraph-gremlin/) - [openCypher project](https://opencypher.org/) — language specification and resources + +The translator’s historical TCK percentage is not a HugeGraph end-to-end compatibility rate; no measured overall HugeGraph Cypher percentage is established here. diff --git a/content/en/docs/language/migrate-from-neo4j.md b/content/en/docs/language/migrate-from-neo4j.md index b40c551d60..c6569d6d2d 100644 --- a/content/en/docs/language/migrate-from-neo4j.md +++ b/content/en/docs/language/migrate-from-neo4j.md @@ -28,11 +28,14 @@ verified and unverified areas and |---|---| | `CREATE INDEX` / `CREATE CONSTRAINT` | Create indexes/constraints through the [schema REST APIs](/docs/clients/restful-api/schema/); Cypher carries no DDL | | Implicit schema (add properties freely) | **Strong schema**: define VertexLabel / EdgeLabel / PropertyKey before writing data | -| Parameterized queries `$param` | Released versions send the raw statement only — a missing binding evaluates to `null` (empty result), so validate values client-side; JSON-bound parameters land in [PR #238](https://github.com/hugegraph/hugegraph/pull/238) | +| Parameterized queries `$param` | Released versions send the raw statement only — a missing binding evaluates to `null` (empty result), so validate values client-side; JSON-bound parameters are available on `master` after [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), with a fixed limit of 16 top-level bindings | | `CALL dbms.*` / `CALL algo.*` procedures | Equivalent capabilities live in the [traverser](/docs/clients/restful-api/traverser/), [task](/docs/clients/restful-api/task/), and other REST APIs | | Driver: Neo4j Bolt driver | [hugegraph-client](/docs/clients/hugegraph-client/) (`CypherManager`) or any HTTP client | | Transaction boundaries inside a Cypher statement | One statement per request; graph-to-graph data migration uses [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/) (preferred — see below), file-based bulk loads use the [HugeGraph Loader](/docs/quickstart/toolchain/hugegraph-loader/) | +The latest published release is 1.7.0 as of 2026-10-09; the merged JSON-bound request form is a +`master` feature, not a promise about that release. See the compatibility notes for its validated contract. + ### Suggested migration path 1. **Inventory your queries**: classify the Cypher in your application against @@ -81,3 +84,5 @@ verified and unverified areas and traversals — see the [equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents); schema DDL and `CALL` procedures map to REST APIs instead. + +The translator’s historical TCK percentage is not a HugeGraph end-to-end compatibility rate; no measured overall HugeGraph Cypher percentage is established here. From 2079bd0baad691b771c81e66b60f64f2e386f56c Mon Sep 17 00:00:00 2001 From: n24q02m Date: Fri, 9 Oct 2026 07:54:52 +0700 Subject: [PATCH 12/17] docs: address cypher page review feedback and refresh nav stats --- .../en/docs/language/cypher-compatibility.md | 10 +++++--- content/en/docs/language/hugegraph-cypher.md | 7 +++++- .../en/docs/language/migrate-from-neo4j.md | 23 ++++++++++++++----- scripts/versioning.py | 12 +++++----- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index 025820683e..e88f200711 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -6,9 +6,10 @@ weight: 3 ### Scope -**The verification results below describe `master`, not a released HugeGraph version.** A released build exposes exactly two +**The verification results below describe `master`, not a released HugeGraph version.** HugeGraph 1.7.0 exposes exactly two request forms on `/graphspaces/{graphspace}/graphs/{graph}/cypher`: `GET ?cypher=` -and `POST application/json` with a raw Cypher body. Released versions accept no bound parameters, and a +and `POST application/json` with a raw Cypher body. Releases before 1.7.0 expose the same two forms under +`/graphs/{graph}/cypher`. Released versions accept no bound parameters, and a statement that references `$param` returns no rows rather than failing — see [Known limitations](/docs/language/hugegraph-cypher/#known-limitations). @@ -46,7 +47,10 @@ Malformed JSON objects and trailing tokens also produce request errors; they do For the JSON-object form, `cypher` must be a nonblank string and `parameters`, if present, must be an object. Omitting `parameters` means an empty map. A referenced but missing binding is an execution error; an explicit -null value is valid. Tests cover string, number, and boolean values, quotes and newlines, the binding names +null value is valid. On the tested tree this execution error applies to every request form, including +`GET ?cypher=` and raw-body `POST`: [#3289](https://github.com/apache/hugegraph/pull/3289) always attaches the +parameters map and rejects unresolved `$param` references, replacing the released null-and-no-rows behaviour +described above. Tests cover string, number, and boolean values, quotes and newlines, the binding names `id` and `label`. The current implementation accepts at most 16 top-level entries in `parameters`; this limit is fixed. Only keys in the top-level `parameters` object count toward it. Cypher does not support a `maxParameters` setting in Gremlin Server's processor configuration. Values remain bindings and do not diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index 38f32bf7c5..a27d67dfba 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -47,6 +47,11 @@ ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.nam ### Basic examples The examples below assume a graph with `person` vertices (`name`, `age`, `city` properties) and `knows` edges. +They assume the labels declare `nullableKeys("age", "city")` on `person` and nullable properties on `knows` — +for example the schema in `scripts/example.groovy` modified with those nullable keys. On a schema without them +(the released default marks `age` and `city` non-null on `person`), the create and update examples below fail +the non-null property check: set every non-null property in each statement, or declare the labels with +`nullableKeys` first. #### Read — MATCH / WHERE / RETURN @@ -136,7 +141,7 @@ Tip: `EXPLAIN MATCH (n:person) RETURN n` is parsed with the `EXPLAIN` option, an Cypher support in HugeGraph is bounded by the transpiler layer, which is based on openCypher 9 era tooling. Known gaps: -- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding evaluates to `null`, so the query returns no rows (or writes null values) rather than failing. Sanitize/escape values on the client side before interpolating them into the statement. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. +- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding evaluates to `null`, so the query returns no rows (or writes null values) rather than failing. Sanitize/escape values on the client side before interpolating them into the statement. On the tested tree with [#3289](https://github.com/apache/hugegraph/pull/3289) merged, this changes: a missing binding is an execution error for every request form, including `GET ?cypher=` and raw-body `POST` — the server always attaches a parameters map and rejects unresolved `$param` references. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. - **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET` and `NOT ... IN` do translate, but they are not verified end-to-end on HugeGraph. The development change verifies two whole-string `=~` matching cases on computed strings; broader regex coverage remains unverified — see the [compatibility notes](/docs/language/cypher-compatibility/). - **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. - **Single statement per request** — multi-statement scripts are not supported; send one statement per call. diff --git a/content/en/docs/language/migrate-from-neo4j.md b/content/en/docs/language/migrate-from-neo4j.md index c6569d6d2d..f0717a6e65 100644 --- a/content/en/docs/language/migrate-from-neo4j.md +++ b/content/en/docs/language/migrate-from-neo4j.md @@ -8,9 +8,11 @@ weight: 4 Neo4j users evaluating HugeGraph. HugeGraph's Cypher coverage is defined by the [`cypher-for-gremlin`](https://github.com/opencypher/cypher-for-gremlin) -translator and is not 1:1 with Neo4j — see the +translator and is not 1:1 with Neo4j — see +[Known limitations](/docs/language/hugegraph-cypher/#known-limitations) for what +released HugeGraph versions do, and the [Cypher compatibility notes](/docs/language/cypher-compatibility/) for the -verified and unverified areas and +development-tree verification record and [HugeGraph Cypher](/docs/language/hugegraph-cypher/) for usage. ### What carries over directly @@ -39,8 +41,11 @@ The latest published release is 1.7.0 as of 2026-10-09; the merged JSON-bound re ### Suggested migration path 1. **Inventory your queries**: classify the Cypher in your application against - the [compatibility notes](/docs/language/cypher-compatibility/) into - "works as-is / rewrite as Gremlin / switch to a REST API". + the [Known limitations](/docs/language/hugegraph-cypher/#known-limitations) + (which describe released behaviour) into + "works as-is / rewrite as Gremlin / switch to a REST API"; the + [compatibility notes](/docs/language/cypher-compatibility/) record only the + development-tree contract. 2. **Create the schema first**: define VertexLabel / EdgeLabel / PropertyKey and indexes through the schema API — HugeGraph requires the schema to exist before data is written. @@ -64,8 +69,14 @@ The latest published release is 1.7.0 as of 2026-10-09; the merged JSON-bound re new in 3.0.0 (schema auto-discovery, multi-label/parallel reads), enabling HugeGraph export and migration workflows. - Map Neo4j properties to HugeGraph PropertyKeys, keep stable vertex IDs stable, map edge - endpoints to existing vertex IDs, and load vertices before edges. These capabilities are + Map Neo4j properties to HugeGraph PropertyKeys and pick the vertex ID strategy + before importing: use `idStrategy = "PRIMARY_KEY"` with a Neo4j business key in + `idFields` and express edge endpoints through those same key fields, or + `idStrategy = "CUSTOMIZE_STRING"` to keep the Neo4j node id. Labels you + pre-created in step 2 must use that same strategy — automatic creation does not + convert an existing `PRIMARY_KEY` label into `CUSTOMIZE_STRING` — and step 2 is + optional when the Sink `mappings` configuration creates the schema. Load vertices + before edges. These capabilities are documented, but a complete Neo4j → HugeGraph migration has not been run end-to-end here — validate examples against your own data before treating them as tested. 4. **Switch incrementally**: keep the queries Cypher can express, and rewrite diff --git a/scripts/versioning.py b/scripts/versioning.py index 2e37d3a435..1d4f0aed2f 100644 --- a/scripts/versioning.py +++ b/scripts/versioning.py @@ -133,36 +133,36 @@ DOCS_NAV_EXPECTED_STATS = { "latest": { "groups": 5, - "pages": 92, + "pages": 95, "removed": 4, "scopedLinks": 0, - "treeSha256": "15de4de385857f877b46083de8e65d2887769d811687c4fe7ade3069401fc929", + "treeSha256": "fd869e8710b268dc59e7f7202cf8ce4bec4061cb7f80af9d9a135070deed72af", }, "1.7": { "groups": 5, "pages": 85, - "removed": 5, + "removed": 8, "scopedLinks": 10, "treeSha256": "c87538b82b0e3506eef59417411686ddc188e0f33d0e3a1cda687de8d6f88747", }, "1.5": { "groups": 5, "pages": 77, - "removed": 13, + "removed": 16, "scopedLinks": 10, "treeSha256": "ac29ab8f0e7020496a3a1afe480687043d751e32c93ffb848e2210e3500cd483", }, "1.3": { "groups": 5, "pages": 68, - "removed": 22, + "removed": 25, "scopedLinks": 10, "treeSha256": "e8c9b0a64dac6dd3e47827ec5072697eb7d3ed79659e0b5c4a9c5df8e1408d38", }, "1.0": { "groups": 5, "pages": 59, - "removed": 21, + "removed": 24, "scopedLinks": 10, "treeSha256": "bd45db511d9b6728e1523bd3c5ebd9d18912ee85aeabf79c77bcca7e511f977a", }, From ad1d0321c0e12aa3db4f83e978309efa9766b5fd Mon Sep 17 00:00:00 2001 From: n24q02m Date: Fri, 9 Oct 2026 07:56:53 +0700 Subject: [PATCH 13/17] docs: mirror cypher review fixes in CN pages --- .../cn/docs/language/cypher-compatibility.md | 9 ++++++--- content/cn/docs/language/hugegraph-cypher.md | 10 ++++++++-- content/cn/docs/language/migrate-from-neo4j.md | 17 +++++++++++------ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index ecb365d910..f735f05b17 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -6,9 +6,10 @@ weight: 3 ### 范围 -**下文验证结果描述的是 `master`,不能直接套用于已发布版本。** 已发布版本在 +**下文验证结果描述的是 `master`,不能直接套用于已发布版本。** HugeGraph 1.7.0 在 `/graphspaces/{graphspace}/graphs/{graph}/cypher` 上只提供两种请求形式:`GET ?cypher=` -和 `POST application/json`(请求体为原始 Cypher 文本)。已发布版本不接受绑定参数,引用 `$param` 的语句 +和 `POST application/json`(请求体为原始 Cypher 文本)。1.7.0 之前的版本在 `/graphs/{graph}/cypher` 下 +提供同样的两种形式。已发布版本不接受绑定参数,引用 `$param` 的语句 不会报错,而是返回空结果——参见[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 本页记录当前 Cypher 开发改动实际验证过的用例,不代表完整支持 openCypher 或 Neo4j,也不代表所有已发布 @@ -44,7 +45,9 @@ JSON 数组、字符串、数字、布尔值或 null 请求体会返回 HTTP 400 格式错误的 JSON 对象和尾随内容也会产生请求错误,不会回退为原始 Cypher 文本。 JSON 对象中的 `cypher` 必须是非空字符串;`parameters` 若提供,必须是对象。省略 `parameters` 表示空参数表。 -语句引用了未提供的参数时会报执行错误;显式传入 `null` 是有效值。测试覆盖字符串、数字、布尔值、引号和换行, +语句引用了未提供的参数时会报执行错误;显式传入 `null` 是有效值。在测试栈上,该执行错误适用于所有请求形式, +包括 `GET ?cypher=` 和原始文本 `POST`:[#3289](https://github.com/apache/hugegraph/pull/3289) 总是附带 +参数表并拒绝未解析的 `$param` 引用,取代了上文描述的已发布版本“返回 null 和空结果”行为。测试覆盖字符串、数字、布尔值、引号和换行, 参数名 `id` 与 `label`。当前实现的 `parameters` 最多接受 16 个顶层条目,该上限固定。 该上限只统计顶层 `parameters` 对象中的键。Cypher 不支持在 Gremlin Server 的处理器配置中设置 `maxParameters`。参数值会作为绑定值传递,不会改写查询文本。 diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index 9cda8ceecd..69336cc755 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -46,7 +46,11 @@ ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.nam ### 基础示例 -以下示例假设图中存在 `person` 顶点(`name`、`age`、`city` 属性)和 `knows` 边。 +以下示例假设图中存在 `person` 顶点(`name`、`age`、`city` 属性)和 `knows` 边,并假设标签 +声明了 `person` 上的 `nullableKeys("age", "city")` 以及 `knows` 上的可空属性——例如在 +`scripts/example.groovy` 的 Schema 上补充这些可空键。若 Schema 未声明(已发布的默认 Schema 把 +`person` 的 `age`、`city` 标记为非空),下面的创建与更新示例会触发非空属性校验失败:请在每条语句中 +为所有非空属性赋值,或先以 `nullableKeys` 声明标签。 #### 查询 — MATCH / WHERE / RETURN @@ -136,7 +140,9 @@ MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代的工具链。已知缺口: -- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被求值为 `null`,查询返回空结果(或写入 null 值)。请在客户端先对值做转义/净化再拼接到语句中。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)已通过合入 `master` 的 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 +- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被求值为 `null`,查询返回空结果(或写入 null 值)。请在客户端先对值做转义/净化再拼接到语句中。在合入 [#3289](https://github.com/apache/hugegraph/pull/3289) 后的 +测试栈上情况改变:缺失的绑定对所有请求形式都是执行错误,包括 `GET ?cypher=` 与原始文本 +`POST`——服务器总是附带参数表并拒绝未解析的 `$param` 引用。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)已通过合入 `master` 的 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 - **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证。开发改动验证了计算字符串上的两个 `=~` 全字符串匹配用例,更广泛的正则覆盖仍未验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 - **不支持 `CALL` 过程** —— HugeGraph 的图算法(最短路径、k-out、personalrank 等)未暴露为 Cypher 过程;请改用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin。 - **每次请求仅一条语句** —— 不支持多语句脚本,请每次调用发送一条语句。 diff --git a/content/cn/docs/language/migrate-from-neo4j.md b/content/cn/docs/language/migrate-from-neo4j.md index 8b67f772b6..91bb952ea4 100644 --- a/content/cn/docs/language/migrate-from-neo4j.md +++ b/content/cn/docs/language/migrate-from-neo4j.md @@ -8,7 +8,8 @@ weight: 4 正在评估 HugeGraph 的 Neo4j 用户。HugeGraph 的 Cypher 覆盖面由 [cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) 转译器决定, -与 Neo4j 并非 1:1 等价 —— 已验证与未验证范围见 +与 Neo4j 并非 1:1 等价 —— 已发布版本的行为见 +[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制),开发树验证记录见 [Cypher 兼容性说明](/cn/docs/language/cypher-compatibility/), 用法见 [HugeGraph Cypher](/cn/docs/language/hugegraph-cypher/)。 @@ -37,8 +38,9 @@ weight: 4 ### 建议的迁移路径 1. **盘点查询**:把应用里的 Cypher 按 - [兼容性说明](/cn/docs/language/cypher-compatibility/) 分成 - "直接可用 / 需改写为 Gremlin / 需换 REST API" 三类。 + [已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)(描述已发布版本行为)分成 + "直接可用 / 需改写为 Gremlin / 需换 REST API" 三类; + [兼容性说明](/cn/docs/language/cypher-compatibility/) 仅记录开发树上的验证结果。 2. **先建 schema**:用 schema API 建好 VertexLabel/EdgeLabel/PropertyKey 和索引 —— HugeGraph 在写入前要求 schema 存在。 3. **导入数据**:首选路径是 [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/) @@ -56,9 +58,12 @@ weight: 4 - [HugeGraph Source](https://seatunnel.apache.org/docs/3.0.0/connectors/source/HugeGraph/) 为 3.0.0 新增(schema 自动发现、多标签/并行读取),使 HugeGraph 的导出与迁移工作流成为可能。 - 将 Neo4j 属性映射为 HugeGraph PropertyKey,保持稳定顶点 ID 不变,把边的端点映射到已存在的 - 顶点 ID,并先导入顶点、后导入边。以上能力均有文档记载,但这里没有完整跑通一次 Neo4j → - HugeGraph 迁移 —— 在把示例当作已验证之前,请先用你自己的数据验证。 + 将 Neo4j 属性映射为 HugeGraph PropertyKey,并在导入前先定好顶点 ID 策略:用 + `idStrategy = "PRIMARY_KEY"` 加 `idFields` 指定 Neo4j 业务键,边的端点也通过这些键字段表达; + 或用 `idStrategy = "CUSTOMIZE_STRING"` 保留 Neo4j 节点 id。第 2 步预创建的标签必须使用同一策略—— + 自动创建不会把已有的 `PRIMARY_KEY` 标签改为 `CUSTOMIZE_STRING`——而当 Sink 的 `mappings` 配置 + 负责创建 schema 时,第 2 步可省略。先导入顶点、后导入边。以上能力均有文档记载,但这里没有完整跑通 + 一次 Neo4j → HugeGraph 迁移 —— 在把示例当作已验证之前,请先用你自己的数据验证。 4. **灰度切换**:Cypher 能表达的查询保持不动, translator 不支持的改写为 Gremlin(等价写法见 [对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法))。 From a49a8c3178d41a102e6c5ab1dd370316ec979d22 Mon Sep 17 00:00:00 2001 From: n24q02m Date: Fri, 9 Oct 2026 10:28:09 +0700 Subject: [PATCH 14/17] docs: re-verify cypher record on merged master and note PK-strategy CREATE limit Signed-off-by: n24q02m --- .../cn/docs/language/cypher-compatibility.md | 20 +++++++++++--- content/cn/docs/language/hugegraph-cypher.md | 5 +++- .../en/docs/language/cypher-compatibility.md | 26 ++++++++++++++----- content/en/docs/language/hugegraph-cypher.md | 5 +++- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index f735f05b17..5650bfaf72 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -14,9 +14,12 @@ weight: 3 本页记录当前 Cypher 开发改动实际验证过的用例,不代表完整支持 openCypher 或 Neo4j,也不代表所有已发布 版本的 HugeGraph 都具备相同行为。测试代码基于当前 Apache `master` 的 -[`af3c686`](https://github.com/apache/hugegraph/commit/af3c6867f4bfa3f95e63ad472c12a88c63529c1b), -该基线声明 HugeGraph `1.8.0`,使用 Java 17 和 TinkerPop `3.8.1`。Cypher 改动独立建立在该基线上。运行栈使用 Java `17.0.20.1`、 -TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。 +[`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb), +该提交声明 HugeGraph `1.8.0`,使用 Java 17 和 TinkerPop `3.8.1`,且 Cypher 改动 +([ASF PR #3289](https://github.com/apache/hugegraph/pull/3289))已合入。运行栈使用 Java `17.0.20.1`(Temurin)、 +TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。合入前在 +[`af3c686`](https://github.com/apache/hugegraph/commit/af3c6867f4bfa3f95e63ad472c12a88c63529c1b) +上的验证仍见下文。 接口路径为 `/graphspaces/{graphspace}/graphs/{graph}/cypher`。一般用法见 [HugeGraph Cypher 指南](/cn/docs/language/hugegraph-cypher/)。 @@ -84,8 +87,17 @@ API 测试夹具使用强类型 Schema,并为 `city` 建立 `SECONDARY` 索引 | 失败写入 | 拒绝双顶点 `CREATE` 后,连续 32 次查询和原生读取均未发现残留 | `testFailedWriteDoesNotLeakIntoLaterRequests` | | 错误与路由 | 非法语法和请求结构、内容类型、参数键与保留的 null 标记、Schema 值、认证及图路由 | `testInvalidRequests`、`testRejectPlainTextPost`、`testRejectInvalidQuery`、`testRejectInvalidBindingShapeAndKeys`、`testRejectTranslatorNullMarker`、`testRejectTranslatorNullSentinelInBindings`、`testAuthenticationAndGraphRouting`、`testSpecifiedGraphRouting` | +合入后在 `5039e5b` 上的补充 REST 验证对全新 RocksDB 图重新执行了文档示例:查询、带排序和 LIMIT 的投影、聚合、 +单顶点 `CREATE`、`SET`/`REMOVE`、边 `DELETE`、`DETACH DELETE`,以及上表全部请求形式约定均与文档一致, +包括三种请求形式下缺失绑定的执行错误。双顶点简写 `CREATE (a)-[:knows]->(b)` 在同一运行中于 `person` 标签使用 +`AUTOMATIC` id 策略的图上验证通过;在 `PRIMARY_KEY` 标签上,同一语句会被拒绝并返回执行错误(提示必须设置主键), +而同一标签上的单顶点 `CREATE` 成功。在 `PRIMARY_KEY` Schema 上,请将两条 `CREATE` 语句分开执行,或对该形式使用 +`AUTOMATIC` id 策略。 + 独立代码改动位于 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289),该 PR 已于 2026-10-08 合入 Apache `master`,合入提交为 -[`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb)。上述固定基线仍对应合入前的实际验证。 +[`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb);上文的验证记录直接描述该合入后的提交, +合入前验证的基线为 +[`af3c686`](https://github.com/apache/hugegraph/commit/af3c6867f4bfa3f95e63ad472c12a88c63529c1b)。 原始开发改动仍关联 [PR #238](https://github.com/hugegraph/hugegraph/pull/238)。 在固定源码提交 [`8d06ad3`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/docs/cypher-compatibility.md) 上,`CypherApiTest` 通过 23/23, diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index 69336cc755..12c723f2c0 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -50,7 +50,10 @@ ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.nam 声明了 `person` 上的 `nullableKeys("age", "city")` 以及 `knows` 上的可空属性——例如在 `scripts/example.groovy` 的 Schema 上补充这些可空键。若 Schema 未声明(已发布的默认 Schema 把 `person` 的 `age`、`city` 标记为非空),下面的创建与更新示例会触发非空属性校验失败:请在每条语句中 -为所有非空属性赋值,或先以 `nullableKeys` 声明标签。 +为所有非空属性赋值,或先以 `nullableKeys` 声明标签。若 `person` 标签使用 `PRIMARY_KEY` id 策略,下面的双顶点简写 +`CREATE (a)-[:knows]->(b)` 会被拒绝并返回执行错误(提示必须设置主键;在已合入 +[#3289](https://github.com/apache/hugegraph/pull/3289) 的 `master` 上验证):请将两条 `CREATE` 语句分开执行, +或对该形式使用 `AUTOMATIC` id 策略。 #### 查询 — MATCH / WHERE / RETURN diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index e88f200711..6562176ca0 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -15,10 +15,13 @@ statement that references `$param` returns no rows rather than failing — see This page records the cases verified for the current Cypher development change. It does not claim full openCypher or Neo4j compatibility, or compatibility across every released HugeGraph version. The tested -working tree is based on current Apache `master` at -[`af3c686`](https://github.com/apache/hugegraph/commit/af3c6867f4bfa3f95e63ad472c12a88c63529c1b), -which declares HugeGraph `1.8.0`, Java 17, and TinkerPop `3.8.1`. This is a standalone Cypher change on that -baseline. The runtime uses Java `17.0.20.1`, TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. +working tree is current Apache `master` at +[`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb), +which declares HugeGraph `1.8.0`, Java 17, and TinkerPop `3.8.1`, with the Cypher change +([#3289](https://github.com/apache/hugegraph/pull/3289)) merged. The runtime uses Java `17.0.20.1` (Temurin), +TinkerPop `3.8.1`, `org.opencypher.gremlin:translation:1.0.4`, and RocksDB. The pre-merge verification on +[`af3c686`](https://github.com/apache/hugegraph/commit/af3c6867f4bfa3f95e63ad472c12a88c63529c1b) remains +referenced below. The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage is covered in the [HugeGraph Cypher guide](/docs/language/hugegraph-cypher/). @@ -93,10 +96,21 @@ Acceptance results are limited to these test cases: | Failed write | A rejected two-vertex `CREATE` left no residue during 32 subsequent query and native-read checks | `testFailedWriteDoesNotLeakIntoLaterRequests` | | Errors and routing | Invalid syntax and request shape, content type, binding keys and the reserved null marker, schema values, authentication, and graph routing | `testInvalidRequests`, `testRejectPlainTextPost`, `testRejectInvalidQuery`, `testRejectInvalidBindingShapeAndKeys`, `testRejectTranslatorNullMarker`, `testRejectTranslatorNullSentinelInBindings`, `testAuthenticationAndGraphRouting`, `testSpecifiedGraphRouting` | +An additional post-merge REST run on `5039e5b` re-executed the documented guide examples against a fresh RocksDB graph: +reads, projection with ordering and limit, aggregation, single-vertex `CREATE`, `SET`/`REMOVE`, edge `DELETE`, +`DETACH DELETE`, and every request-form contract above held, including the missing-binding execution error on all +three forms. The two-vertex shorthand `CREATE (a)-[:knows]->(b)` was verified in the same run on a graph whose +`person` label uses the `AUTOMATIC` id strategy; on a `PRIMARY_KEY` label the same statement is rejected with an +execution error reporting that the primary keys must be set, while single-vertex `CREATE` on that label succeeds. +On `PRIMARY_KEY` schemas, issue the two `CREATE` statements separately or use the `AUTOMATIC` id strategy for this form. + The standalone code change is in [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), which was merged into Apache `master` on 2026-10-08 as -[`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb). -The verified pre-merge baseline remains pinned above. The original development +[`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb); +the verification record above describes that merged tree directly. The pre-merge baseline verified before the +merge is +[`af3c686`](https://github.com/apache/hugegraph/commit/af3c6867f4bfa3f95e63ad472c12a88c63529c1b). +The original development change remains linked in [PR #238](https://github.com/hugegraph/hugegraph/pull/238). At source commit [`8d06ad3`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/docs/cypher-compatibility.md), `CypherApiTest` passed 23/23, `CypherClientTest` 7/7, and `CypherOpProcessorTest` 8/8, with no skips. The additional predicate, diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index a27d67dfba..d9c39597e0 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -51,7 +51,10 @@ They assume the labels declare `nullableKeys("age", "city")` on `person` and nul for example the schema in `scripts/example.groovy` modified with those nullable keys. On a schema without them (the released default marks `age` and `city` non-null on `person`), the create and update examples below fail the non-null property check: set every non-null property in each statement, or declare the labels with -`nullableKeys` first. +`nullableKeys` first. If the `person` label uses the `PRIMARY_KEY` id strategy, the two-vertex shorthand +`CREATE (a)-[:knows]->(b)` below is rejected with an execution error reporting that the primary keys must be set +(verified on `master` with [#3289](https://github.com/apache/hugegraph/pull/3289) merged): issue the two +`CREATE` statements separately or use the `AUTOMATIC` id strategy for that form. #### Read — MATCH / WHERE / RETURN From 4290c2bb2e63f720790a72ad2ea3278336f9c272 Mon Sep 17 00:00:00 2001 From: n24q02m Date: Mon, 12 Oct 2026 15:19:11 +0700 Subject: [PATCH 15/17] fix: address remaining review comments on the Cypher language pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Basic auth: note that credentials must be URL-safe Base64 and the password cannot contain ':' - Narrow the "$param returns no rows" claim: 1.7.0 inlines a missing binding as null, so predicates match nothing but RETURN $value still returns a row - Rewrite the edge CREATE example to create the vertices first and then MATCH them, since PRIMARY_KEY labels reject the multi-vertex shorthand - Point the index/constraint link at the IndexLabel REST API page - Fix the SeaTunnel 3.0.0 docs link - Correct the TCK pass rate to ~91.8% (879/958) - CN: use 非空白字符串 Co-Authored-By: Claude Sonnet 5.5 --- .../cn/docs/language/cypher-compatibility.md | 8 ++++---- content/cn/docs/language/hugegraph-cypher.md | 18 ++++++++++------- .../cn/docs/language/migrate-from-neo4j.md | 10 +++++----- .../en/docs/language/cypher-compatibility.md | 10 ++++++---- content/en/docs/language/hugegraph-cypher.md | 20 +++++++++++-------- .../en/docs/language/migrate-from-neo4j.md | 10 +++++----- 6 files changed, 43 insertions(+), 33 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index 5650bfaf72..da8dee5b72 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -10,7 +10,7 @@ weight: 3 `/graphspaces/{graphspace}/graphs/{graph}/cypher` 上只提供两种请求形式:`GET ?cypher=` 和 `POST application/json`(请求体为原始 Cypher 文本)。1.7.0 之前的版本在 `/graphs/{graph}/cypher` 下 提供同样的两种形式。已发布版本不接受绑定参数,引用 `$param` 的语句 -不会报错,而是返回空结果——参见[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 +不会报错,缺失的绑定会被内联为 `null`(基于它的谓词匹配不到行,而 `RETURN $value AS value` 仍会返回一行)——参见[已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 本页记录当前 Cypher 开发改动实际验证过的用例,不代表完整支持 openCypher 或 Neo4j,也不代表所有已发布 版本的 HugeGraph 都具备相同行为。测试代码基于当前 Apache `master` 的 @@ -34,7 +34,7 @@ TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。合 | `POST application/json`,请求体为 JSON 对象 | 否 — 由 [#3289](https://github.com/apache/hugegraph/pull/3289) 引入 | 查询语句与参数分开传入 | `testParameters` | 因此下面的 JSON 对象形式**在任何已发布的 HugeGraph 版本中都不可用**,它描述已合入 `master`(1.8.0 开发线)的改动。 -在已发布版本上,引用 `$param` 的语句会把该参数绑定为 `null` 并返回空结果——参见 +在已发布版本上,引用 `$param` 的语句会把缺失的绑定内联为 `null`,是否返回行取决于表达式(`WHERE n.name = $name` 匹配不到行,`RETURN $value AS value` 会返回一行 `null`)——参见 [已知限制](/cn/docs/language/hugegraph-cypher/#已知限制)。 ```json @@ -47,10 +47,10 @@ TinkerPop `3.8.1`、`org.opencypher.gremlin:translation:1.0.4` 和 RocksDB。合 JSON 数组、字符串、数字、布尔值或 null 请求体会返回 HTTP 400。 格式错误的 JSON 对象和尾随内容也会产生请求错误,不会回退为原始 Cypher 文本。 -JSON 对象中的 `cypher` 必须是非空字符串;`parameters` 若提供,必须是对象。省略 `parameters` 表示空参数表。 +JSON 对象中的 `cypher` 必须是非空白字符串;`parameters` 若提供,必须是对象。省略 `parameters` 表示空参数表。 语句引用了未提供的参数时会报执行错误;显式传入 `null` 是有效值。在测试栈上,该执行错误适用于所有请求形式, 包括 `GET ?cypher=` 和原始文本 `POST`:[#3289](https://github.com/apache/hugegraph/pull/3289) 总是附带 -参数表并拒绝未解析的 `$param` 引用,取代了上文描述的已发布版本“返回 null 和空结果”行为。测试覆盖字符串、数字、布尔值、引号和换行, +参数表并拒绝未解析的 `$param` 引用,取代了上文描述的已发布版本“缺失绑定按 `null` 处理”行为。测试覆盖字符串、数字、布尔值、引号和换行, 参数名 `id` 与 `label`。当前实现的 `parameters` 最多接受 16 个顶层条目,该上限固定。 该上限只统计顶层 `parameters` 对象中的键。Cypher 不支持在 Gremlin Server 的处理器配置中设置 `maxParameters`。参数值会作为绑定值传递,不会改写查询文本。 diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index 12c723f2c0..c94e11caa3 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -29,7 +29,7 @@ GET /graphspaces/{graphspace}/graphs/{graph}/cypher?cypher={statement} POST /graphspaces/{graphspace}/graphs/{graph}/cypher ``` -该端点始终要求 `Authorization` 头(`Basic` 或 `Bearer`),即使服务端未开启认证 —— 凭据会被转发给 Gremlin Server。完整的请求/响应格式见 [Cypher REST API 参考](/cn/docs/clients/restful-api/cypher/)。 +该端点始终要求 `Authorization` 头(`Basic` 或 `Bearer`),即使服务端未开启认证 —— 凭据会被转发给 Gremlin Server。`Basic` 凭据必须使用 URL 安全的 Base64 编码(用 `-` 和 `_` 代替 `+` 和 `/`),且密码不能包含 `:`;无法满足这两个条件的账号请改用 `Bearer`。完整的请求/响应格式见 [Cypher REST API 参考](/cn/docs/clients/restful-api/cypher/)。 示例: @@ -50,10 +50,10 @@ ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.nam 声明了 `person` 上的 `nullableKeys("age", "city")` 以及 `knows` 上的可空属性——例如在 `scripts/example.groovy` 的 Schema 上补充这些可空键。若 Schema 未声明(已发布的默认 Schema 把 `person` 的 `age`、`city` 标记为非空),下面的创建与更新示例会触发非空属性校验失败:请在每条语句中 -为所有非空属性赋值,或先以 `nullableKeys` 声明标签。若 `person` 标签使用 `PRIMARY_KEY` id 策略,下面的双顶点简写 +为所有非空属性赋值,或先以 `nullableKeys` 声明标签。若 `person` 标签使用 `PRIMARY_KEY` id 策略(`scripts/example.groovy` 即如此),双顶点简写 `CREATE (a)-[:knows]->(b)` 会被拒绝并返回执行错误(提示必须设置主键;在已合入 -[#3289](https://github.com/apache/hugegraph/pull/3289) 的 `master` 上验证):请将两条 `CREATE` 语句分开执行, -或对该形式使用 `AUTOMATIC` id 策略。 +[#3289](https://github.com/apache/hugegraph/pull/3289) 的 `master` 上验证),因此下面的边示例先分别创建顶点再匹配它们; +该简写在 `AUTOMATIC` id 策略下可用。 #### 查询 — MATCH / WHERE / RETURN @@ -86,8 +86,12 @@ CREATE (n:person {name: 'josh', age: 32, city: 'beijing'}) ``` ```cypher -// 创建两个顶点及它们之间的边 -CREATE (a:person {name: 'peter'})-[:knows]->(b:person {name: 'lop'}) +// 先创建两个顶点,再创建它们之间的边(每条语句单独作为一次请求发送) +CREATE (:person {name: 'peter'}) +CREATE (:person {name: 'lop'}) +MATCH (a:person), (b:person) +WHERE a.name = 'peter' AND b.name = 'lop' +CREATE (a)-[:knows]->(b) ``` #### 更新 — SET / REMOVE @@ -143,7 +147,7 @@ MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代的工具链。已知缺口: -- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被求值为 `null`,查询返回空结果(或写入 null 值)。请在客户端先对值做转义/净化再拼接到语句中。在合入 [#3289](https://github.com/apache/hugegraph/pull/3289) 后的 +- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被内联为 `null`,结果取决于表达式:`WHERE n.name = $name` 这类谓词匹配不到行,`RETURN $value AS value` 仍会返回一行 `null`,写入时则会写入 null 值。请在客户端先对值做转义/净化再拼接到语句中。在合入 [#3289](https://github.com/apache/hugegraph/pull/3289) 后的 测试栈上情况改变:缺失的绑定对所有请求形式都是执行错误,包括 `GET ?cypher=` 与原始文本 `POST`——服务器总是附带参数表并拒绝未解析的 `$param` 引用。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)已通过合入 `master` 的 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 - **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证。开发改动验证了计算字符串上的两个 `=~` 全字符串匹配用例,更广泛的正则覆盖仍未验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 diff --git a/content/cn/docs/language/migrate-from-neo4j.md b/content/cn/docs/language/migrate-from-neo4j.md index 91bb952ea4..152ad361ce 100644 --- a/content/cn/docs/language/migrate-from-neo4j.md +++ b/content/cn/docs/language/migrate-from-neo4j.md @@ -26,9 +26,9 @@ weight: 4 | 在 Neo4j 里 | 在 HugeGraph 里 | |---|---| -| `CREATE INDEX` / `CREATE CONSTRAINT` | 通过 [schema REST API](/cn/docs/clients/restful-api/schema/) 建索引/约束;Cypher 不承载 DDL | +| `CREATE INDEX` / `CREATE CONSTRAINT` | 通过 [IndexLabel REST API](/cn/docs/clients/restful-api/indexlabel/) 建索引/约束;Cypher 不承载 DDL | | 隐式 schema(属性随意添加) | **强 schema**:先定义 VertexLabel/EdgeLabel/PropertyKey,再写数据 | -| 参数化查询 `$param` | 已发布版本仅发送原始语句 —— 缺失的绑定会被求值为 `null`(空结果),请在客户端校验取值;JSON 绑定参数已通过 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 合入 `master`,固定最多 16 个顶层绑定参数 | +| 参数化查询 `$param` | 已发布版本仅发送原始语句 —— 缺失的绑定会被内联为 `null` 而不是报错(基于它的谓词匹配不到行),请在客户端校验取值;JSON 绑定参数已通过 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 合入 `master`,固定最多 16 个顶层绑定参数 | | `CALL dbms.*` / `CALL algo.*` 过程 | 对应功能分散在 [traverser](/cn/docs/clients/restful-api/traverser/)、[task](/cn/docs/clients/restful-api/task/) 等 REST API | | 驱动:Neo4j Bolt driver | [hugegraph-client](/cn/docs/clients/hugegraph-client/)(`CypherManager`)或任意 HTTP 客户端 | | 事务边界在 Cypher 语句内 | 每次请求一个语句;图到图的数据迁移使用 [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/)(首选 —— 见下文),基于文件的批量导入使用 [HugeGraph Loader](/cn/docs/quickstart/toolchain/hugegraph-loader/) | @@ -50,7 +50,7 @@ weight: 4 HugeGraph 侧的环境准备、`mappings` 配置与顶点/边导入示例见 [通过 SeaTunnel Sink 导入图数据](/cn/docs/quickstart/toolchain/import/hugegraph-seatunnel-connector/)。 - [SeaTunnel 3.0.0 连接器文档](https://seatunnel.apache.org/docs/3.0.0/about/) 说明了可依赖的能力: + [SeaTunnel 3.0.0 连接器文档](https://seatunnel.apache.org/docs/3.0.0/introduction/about/) 说明了可依赖的能力: - [Neo4j Source](https://seatunnel.apache.org/docs/3.0.0/connectors/source/Neo4j/) 以显式字段 schema 读取 Cypher 查询结果;3.0.0 新增通过 `tables_configs` 的多表读取。 - [HugeGraph Sink](https://seatunnel.apache.org/docs/3.0.0/connectors/sink/HugeGraph/) 在 3.0.0 @@ -69,10 +69,10 @@ weight: 4 ### 已知限制速查 -- 已发布版本不支持参数绑定(缺失的绑定会被求值为 `null`,见上表)、 +- 已发布版本不支持参数绑定(缺失的绑定会被内联为 `null`,见上表)、 多语句脚本与 `CALL` 过程。 - 转译器最后一次发布是 2019-11(1.0.4),其自身 TCK 报告为 - 879 通过 / 79 失败(约 91.7%)—— 未覆盖的语法会在翻译期报错。 + 879 通过 / 79 失败(约 91.8%)—— 未覆盖的语法会在翻译期报错。 - 不受支持的查询结构通常可以改写为等价的 Gremlin 遍历 —— 见 [HugeGraph Cypher 的对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法); schema DDL 与 `CALL` 过程请改用 REST API。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index 6562176ca0..8eab8cd72c 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -10,7 +10,8 @@ weight: 3 request forms on `/graphspaces/{graphspace}/graphs/{graph}/cypher`: `GET ?cypher=` and `POST application/json` with a raw Cypher body. Releases before 1.7.0 expose the same two forms under `/graphs/{graph}/cypher`. Released versions accept no bound parameters, and a -statement that references `$param` returns no rows rather than failing — see +statement that references `$param` runs with the missing binding inlined as `null` rather than failing (a predicate on it matches no rows, +while `RETURN $value AS value` still returns a row) — see [Known limitations](/docs/language/hugegraph-cypher/#known-limitations). This page records the cases verified for the current Cypher development change. It does not claim full @@ -35,8 +36,9 @@ The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage | `POST text/plain` with any body | No | Rejected with HTTP 415 | `testRejectPlainTextPost` | | `POST application/json` with a JSON object | No — introduced by [#3289](https://github.com/apache/hugegraph/pull/3289) | Query and bindings are sent separately | `testParameters` | -The JSON object form below is therefore **not available in any released HugeGraph version**; it describes the merged change on `master` (the 1.8.0 development line). On released versions a statement using `$param` runs with that binding bound to `null` and -returns no rows — see [Known limitations](/docs/language/hugegraph-cypher/#known-limitations). +The JSON object form below is therefore **not available in any released HugeGraph version**; it describes the merged change on `master` (the 1.8.0 development line). On released versions a statement using `$param` runs with the missing binding inlined as `null`; whether it returns rows +depends on the expression (`WHERE n.name = $name` matches nothing, `RETURN $value AS value` returns a row holding `null`) — +see [Known limitations](/docs/language/hugegraph-cypher/#known-limitations). ```json { @@ -52,7 +54,7 @@ For the JSON-object form, `cypher` must be a nonblank string and `parameters`, i Omitting `parameters` means an empty map. A referenced but missing binding is an execution error; an explicit null value is valid. On the tested tree this execution error applies to every request form, including `GET ?cypher=` and raw-body `POST`: [#3289](https://github.com/apache/hugegraph/pull/3289) always attaches the -parameters map and rejects unresolved `$param` references, replacing the released null-and-no-rows behaviour +parameters map and rejects unresolved `$param` references, replacing the released null-binding behaviour described above. Tests cover string, number, and boolean values, quotes and newlines, the binding names `id` and `label`. The current implementation accepts at most 16 top-level entries in `parameters`; this limit is fixed. Only keys in the top-level `parameters` object count toward it. Cypher does not support a diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index d9c39597e0..6643580798 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -29,7 +29,7 @@ GET /graphspaces/{graphspace}/graphs/{graph}/cypher?cypher={statement} POST /graphspaces/{graphspace}/graphs/{graph}/cypher ``` -The endpoint always requires an `Authorization` header (`Basic` or `Bearer`), even when server authentication is disabled — the credentials are forwarded to the Gremlin Server. See the [Cypher REST API reference](/docs/clients/restful-api/cypher/) for the full request/response format. +The endpoint always requires an `Authorization` header (`Basic` or `Bearer`), even when server authentication is disabled — the credentials are forwarded to the Gremlin Server. `Basic` credentials must be encoded with URL-safe Base64 (`-` and `_` instead of `+` and `/`), and the password must not contain `:`; use `Bearer` for accounts that cannot meet either condition. See the [Cypher REST API reference](/docs/clients/restful-api/cypher/) for the full request/response format. Example: @@ -51,10 +51,10 @@ They assume the labels declare `nullableKeys("age", "city")` on `person` and nul for example the schema in `scripts/example.groovy` modified with those nullable keys. On a schema without them (the released default marks `age` and `city` non-null on `person`), the create and update examples below fail the non-null property check: set every non-null property in each statement, or declare the labels with -`nullableKeys` first. If the `person` label uses the `PRIMARY_KEY` id strategy, the two-vertex shorthand -`CREATE (a)-[:knows]->(b)` below is rejected with an execution error reporting that the primary keys must be set -(verified on `master` with [#3289](https://github.com/apache/hugegraph/pull/3289) merged): issue the two -`CREATE` statements separately or use the `AUTOMATIC` id strategy for that form. +`nullableKeys` first. If the `person` label uses the `PRIMARY_KEY` id strategy (as it does in `scripts/example.groovy`), the two-vertex +shorthand `CREATE (a)-[:knows]->(b)` is rejected with an execution error reporting that the primary keys must be set +(verified on `master` with [#3289](https://github.com/apache/hugegraph/pull/3289) merged), so the edge example below creates the vertices +first and then matches them. The shorthand works with the `AUTOMATIC` id strategy. #### Read — MATCH / WHERE / RETURN @@ -87,8 +87,12 @@ CREATE (n:person {name: 'josh', age: 32, city: 'beijing'}) ``` ```cypher -// Create two vertices and an edge between them -CREATE (a:person {name: 'peter'})-[:knows]->(b:person {name: 'lop'}) +// Create two vertices, then an edge between them (send each statement as its own request) +CREATE (:person {name: 'peter'}) +CREATE (:person {name: 'lop'}) +MATCH (a:person), (b:person) +WHERE a.name = 'peter' AND b.name = 'lop' +CREATE (a)-[:knows]->(b) ``` #### Update — SET / REMOVE @@ -144,7 +148,7 @@ Tip: `EXPLAIN MATCH (n:person) RETURN n` is parsed with the `EXPLAIN` option, an Cypher support in HugeGraph is bounded by the transpiler layer, which is based on openCypher 9 era tooling. Known gaps: -- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding evaluates to `null`, so the query returns no rows (or writes null values) rather than failing. Sanitize/escape values on the client side before interpolating them into the statement. On the tested tree with [#3289](https://github.com/apache/hugegraph/pull/3289) merged, this changes: a missing binding is an execution error for every request form, including `GET ?cypher=` and raw-body `POST` — the server always attaches a parameters map and rejects unresolved `$param` references. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. +- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding is inlined as `null` rather than failing, and the result depends on the expression: a predicate such as `WHERE n.name = $name` matches no rows, `RETURN $value AS value` still returns a row holding `null`, and a write stores a null value. Sanitize/escape values on the client side before interpolating them into the statement. On the tested tree with [#3289](https://github.com/apache/hugegraph/pull/3289) merged, this changes: a missing binding is an execution error for every request form, including `GET ?cypher=` and raw-body `POST` — the server always attaches a parameters map and rejects unresolved `$param` references. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. - **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET` and `NOT ... IN` do translate, but they are not verified end-to-end on HugeGraph. The development change verifies two whole-string `=~` matching cases on computed strings; broader regex coverage remains unverified — see the [compatibility notes](/docs/language/cypher-compatibility/). - **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. - **Single statement per request** — multi-statement scripts are not supported; send one statement per call. diff --git a/content/en/docs/language/migrate-from-neo4j.md b/content/en/docs/language/migrate-from-neo4j.md index f0717a6e65..a184bcd75e 100644 --- a/content/en/docs/language/migrate-from-neo4j.md +++ b/content/en/docs/language/migrate-from-neo4j.md @@ -28,9 +28,9 @@ development-tree verification record and | In Neo4j | In HugeGraph | |---|---| -| `CREATE INDEX` / `CREATE CONSTRAINT` | Create indexes/constraints through the [schema REST APIs](/docs/clients/restful-api/schema/); Cypher carries no DDL | +| `CREATE INDEX` / `CREATE CONSTRAINT` | Create indexes/constraints through the [IndexLabel REST API](/docs/clients/restful-api/indexlabel/); Cypher carries no DDL | | Implicit schema (add properties freely) | **Strong schema**: define VertexLabel / EdgeLabel / PropertyKey before writing data | -| Parameterized queries `$param` | Released versions send the raw statement only — a missing binding evaluates to `null` (empty result), so validate values client-side; JSON-bound parameters are available on `master` after [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), with a fixed limit of 16 top-level bindings | +| Parameterized queries `$param` | Released versions send the raw statement only — a missing binding is inlined as `null` instead of failing (a predicate on it matches no rows), so validate values client-side; JSON-bound parameters are available on `master` after [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), with a fixed limit of 16 top-level bindings | | `CALL dbms.*` / `CALL algo.*` procedures | Equivalent capabilities live in the [traverser](/docs/clients/restful-api/traverser/), [task](/docs/clients/restful-api/task/), and other REST APIs | | Driver: Neo4j Bolt driver | [hugegraph-client](/docs/clients/hugegraph-client/) (`CypherManager`) or any HTTP client | | Transaction boundaries inside a Cypher statement | One statement per request; graph-to-graph data migration uses [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/) (preferred — see below), file-based bulk loads use the [HugeGraph Loader](/docs/quickstart/toolchain/hugegraph-loader/) | @@ -58,7 +58,7 @@ The latest published release is 1.7.0 as of 2026-10-09; the merged JSON-bound re (environment, `mappings`, vertex/edge import examples) is covered in the [Import Graph Data with SeaTunnel Sink guide](/docs/quickstart/toolchain/import/hugegraph-seatunnel-connector/). - The [SeaTunnel 3.0.0 connector docs](https://seatunnel.apache.org/docs/3.0.0/about/) document + The [SeaTunnel 3.0.0 connector docs](https://seatunnel.apache.org/docs/3.0.0/introduction/about/) document what to rely on: - [Neo4j Source](https://seatunnel.apache.org/docs/3.0.0/connectors/source/Neo4j/) reads Cypher query results with explicit field schemas; 3.0.0 adds multi-table reads via `tables_configs`. @@ -87,10 +87,10 @@ The latest published release is 1.7.0 as of 2026-10-09; the merged JSON-bound re ### Known limitations at a glance - Released versions support neither parameter binding (a missing binding - evaluates to `null` — see the habits table), multi-statement + is inlined as `null` — see the habits table), multi-statement scripts, nor `CALL` procedures. - The translator's last release is 2019-11 (1.0.4); its own TCK self-report is - 879 pass / 79 fail (~91.7%) — uncovered syntax fails at translation time. + 879 pass / 79 fail (~91.8%) — uncovered syntax fails at translation time. - Unsupported query constructs can typically be rewritten as Gremlin traversals — see the [equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents); From 21083db914b25788255b617ce588fd7d4cb850db Mon Sep 17 00:00:00 2001 From: n24q02m Date: Wed, 14 Oct 2026 07:25:03 +0700 Subject: [PATCH 16/17] fix: address review on Cypher guide and Neo4j migration page - Add a RANGE index on person.age to the assumed schema and state that property predicates need a covering index (mirrored in the habits table of the migration page and the compatibility notes). - Use names absent from scripts/example.groovy (alice/bob/carol) in the create/update/delete examples so PRIMARY_KEY ids do not replace seed vertices. - Document that a missing $param in a write removes the property on SET and stores a marker string or fails on CREATE (reviewer-measured on 1.7.0). - Rewrite the SeaTunnel step: idFields are required for every non-AUTOMATIC strategy, edges need sourceConfig/targetConfig.idFields, the query must return the ID column, and mappings do not create IndexLabels. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01LHLbjw9SjXQc47Zj7eFuAd --- .../cn/docs/language/cypher-compatibility.md | 6 +++++ content/cn/docs/language/hugegraph-cypher.md | 26 +++++++++++------- .../cn/docs/language/migrate-from-neo4j.md | 22 ++++++++++----- .../en/docs/language/cypher-compatibility.md | 7 +++++ content/en/docs/language/hugegraph-cypher.md | 27 ++++++++++++------- .../en/docs/language/migrate-from-neo4j.md | 27 +++++++++++++------ 6 files changed, 80 insertions(+), 35 deletions(-) diff --git a/content/cn/docs/language/cypher-compatibility.md b/content/cn/docs/language/cypher-compatibility.md index da8dee5b72..f84690910d 100644 --- a/content/cn/docs/language/cypher-compatibility.md +++ b/content/cn/docs/language/cypher-compatibility.md @@ -94,6 +94,12 @@ API 测试夹具使用强类型 Schema,并为 `city` 建立 `SECONDARY` 索引 而同一标签上的单顶点 `CREATE` 成功。在 `PRIMARY_KEY` Schema 上,请将两条 `CREATE` 语句分开执行,或对该形式使用 `AUTOMATIC` id 策略。 +指南中有两个示例依赖 Schema。范围谓词查询(`WHERE n.age > 30`)需要上文夹具 Schema 中声明的 `age` 上的 `RANGE` 索引; +`scripts/example.groovy` 的 Schema 只为 `person` 建了 `SECONDARY` 索引(`city`,以及 `age` 与 `city` 的组合), +因此在那里对 `age` 做范围比较会被拒绝并报“未建索引”错误,直到建立 `RANGE` 索引。创建、更新和删除示例随后改名为 +`alice`、`bob` 和 `carol`,因为 `scripts/example.groovy` 已预置 `marko`、`vadas`、`josh` 和 `peter`,而在 `PRIMARY_KEY` 标签上 +用预置名字执行 `CREATE` 会替换该顶点;改名只改动数据取值,没有作为单独的验证重新运行。 + 独立代码改动位于 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289),该 PR 已于 2026-10-08 合入 Apache `master`,合入提交为 [`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb);上文的验证记录直接描述该合入后的提交, 合入前验证的基线为 diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index c94e11caa3..a8cca634b6 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -47,8 +47,14 @@ ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.nam ### 基础示例 以下示例假设图中存在 `person` 顶点(`name`、`age`、`city` 属性)和 `knows` 边,并假设标签 -声明了 `person` 上的 `nullableKeys("age", "city")` 以及 `knows` 上的可空属性——例如在 -`scripts/example.groovy` 的 Schema 上补充这些可空键。若 Schema 未声明(已发布的默认 Schema 把 +声明了 `person` 上的 `nullableKeys("age", "city")` 以及 `knows` 上的可空属性,并且 `person.age` 上有 `RANGE` 索引——例如在 +`scripts/example.groovy` 的 Schema 上补充这些可空键,再加上 +`schema.indexLabel("personByAge").onV("person").by("age").range().ifNotExist().create()`。`WHERE` 中的属性谓词必须有索引覆盖: +`scripts/example.groovy` 只为 `person.city` 以及 `(age, city)` 建了 `SECONDARY` 索引,因此在 `RANGE` 索引存在之前, +`n.age > 30` 这类范围比较会被拒绝并报“未建索引”错误。 +若先加载 `scripts/example.groovy`,请注意它已经预置了 `person` 顶点 `marko`、`vadas`、`josh` 和 `peter`; +由于 `person` 标签使用 `PRIMARY_KEY` id 策略,用这些名字执行 `CREATE` 会替换预置顶点, +因此下面的创建、更新和删除示例使用示例数据中不存在的名字(`alice`、`bob`、`carol`),或请在空图上执行。若 Schema 未声明可空键(已发布的默认 Schema 把 `person` 的 `age`、`city` 标记为非空),下面的创建与更新示例会触发非空属性校验失败:请在每条语句中 为所有非空属性赋值,或先以 `nullableKeys` 声明标签。若 `person` 标签使用 `PRIMARY_KEY` id 策略(`scripts/example.groovy` 即如此),双顶点简写 `CREATE (a)-[:knows]->(b)` 会被拒绝并返回执行错误(提示必须设置主键;在已合入 @@ -82,22 +88,22 @@ RETURN b.name AS friend ```cypher // 创建顶点 -CREATE (n:person {name: 'josh', age: 32, city: 'beijing'}) +CREATE (n:person {name: 'alice', age: 32, city: 'beijing'}) ``` ```cypher // 先创建两个顶点,再创建它们之间的边(每条语句单独作为一次请求发送) -CREATE (:person {name: 'peter'}) -CREATE (:person {name: 'lop'}) +CREATE (:person {name: 'bob'}) +CREATE (:person {name: 'carol'}) MATCH (a:person), (b:person) -WHERE a.name = 'peter' AND b.name = 'lop' +WHERE a.name = 'bob' AND b.name = 'carol' CREATE (a)-[:knows]->(b) ``` #### 更新 — SET / REMOVE ```cypher -MATCH (n:person) WHERE n.name = 'josh' +MATCH (n:person) WHERE n.name = 'alice' SET n.age = 33 REMOVE n.city ``` @@ -107,13 +113,13 @@ REMOVE n.city ```cypher // 删除边 MATCH (a:person)-[r:knows]->(b:person) -WHERE a.name = 'peter' AND b.name = 'lop' +WHERE a.name = 'bob' AND b.name = 'carol' DELETE r ``` ```cypher // 删除顶点及其所有边 -MATCH (n:person) WHERE n.name = 'josh' +MATCH (n:person) WHERE n.name = 'alice' DETACH DELETE n ``` @@ -147,7 +153,7 @@ MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代的工具链。已知缺口: -- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被内联为 `null`,结果取决于表达式:`WHERE n.name = $name` 这类谓词匹配不到行,`RETURN $value AS value` 仍会返回一行 `null`,写入时则会写入 null 值。请在客户端先对值做转义/净化再拼接到语句中。在合入 [#3289](https://github.com/apache/hugegraph/pull/3289) 后的 +- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被内联为 `null`,结果取决于表达式:`WHERE n.name = $name` 这类谓词匹配不到行,`RETURN $value AS value` 仍会返回一行 `null`。缺失绑定的写入并不能可靠地存入 null 值:视语句而定,`SET n.prop = $missing` 会移除已有属性,`CREATE (n:label {prop: $missing})` 会在文本属性中存入转译库的 null 标记字符串 `" cypher.null"`,而对非文本属性执行同样的 `CREATE`,或对非空属性执行 `SET`,则会报错。请在客户端先对值做转义/净化再拼接到语句中。在合入 [#3289](https://github.com/apache/hugegraph/pull/3289) 后的 测试栈上情况改变:缺失的绑定对所有请求形式都是执行错误,包括 `GET ?cypher=` 与原始文本 `POST`——服务器总是附带参数表并拒绝未解析的 `$param` 引用。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)已通过合入 `master` 的 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 - **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证。开发改动验证了计算字符串上的两个 `=~` 全字符串匹配用例,更广泛的正则覆盖仍未验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 diff --git a/content/cn/docs/language/migrate-from-neo4j.md b/content/cn/docs/language/migrate-from-neo4j.md index 152ad361ce..4a25948f5f 100644 --- a/content/cn/docs/language/migrate-from-neo4j.md +++ b/content/cn/docs/language/migrate-from-neo4j.md @@ -18,7 +18,7 @@ weight: 4 | Neo4j 概念 | HugeGraph 对应 | |---|---| | 属性图模型(节点/关系/属性) | 相同 —— 顶点标签 / 边标签 / 属性 | -| 基础 Cypher:`MATCH`/`WHERE`/`RETURN`/`CREATE`/`SET`/`DELETE` | 直接可用(REST `/cypher` 端点或 Java 客户端 `CypherManager`) | +| 基础 Cypher:`MATCH`/`WHERE`/`RETURN`/`CREATE`/`SET`/`DELETE` | 直接可用(REST `/cypher` 端点或 Java 客户端 `CypherManager`),但须遵守下文的 Schema 与索引规则 | | 简单聚合(`count`/`sum`/`min`/`max`/`avg`) | 直接可用 | | 依赖图遍历的查询需求 | Gremlin 遍历或 [traverser REST API](/cn/docs/clients/restful-api/traverser/)(k-out、最短路、personalrank 等) | @@ -28,7 +28,8 @@ weight: 4 |---|---| | `CREATE INDEX` / `CREATE CONSTRAINT` | 通过 [IndexLabel REST API](/cn/docs/clients/restful-api/indexlabel/) 建索引/约束;Cypher 不承载 DDL | | 隐式 schema(属性随意添加) | **强 schema**:先定义 VertexLabel/EdgeLabel/PropertyKey,再写数据 | -| 参数化查询 `$param` | 已发布版本仅发送原始语句 —— 缺失的绑定会被内联为 `null` 而不是报错(基于它的谓词匹配不到行),请在客户端校验取值;JSON 绑定参数已通过 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 合入 `master`,固定最多 16 个顶层绑定参数 | +| `WHERE` 中的属性谓词无需索引 | `WHERE` 中针对属性的谓词必须有索引覆盖:请先创建 `SECONDARY` 或 `RANGE` 的 IndexLabel,`>`、`<` 等范围比较需要 `RANGE`。没有覆盖索引时,请求会返回 `status.code` 400 和“未建索引”错误 | +| 参数化查询 `$param` | 已发布版本仅发送原始语句 —— 缺失的绑定会被内联为 `null` 而不是报错(基于它的谓词匹配不到行,写入也不能可靠地存入 `null`:`SET` 会移除属性,`CREATE` 可能存入标记字符串 `" cypher.null"` 或报错),请在客户端校验取值;JSON 绑定参数已通过 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 合入 `master`,固定最多 16 个顶层绑定参数 | | `CALL dbms.*` / `CALL algo.*` 过程 | 对应功能分散在 [traverser](/cn/docs/clients/restful-api/traverser/)、[task](/cn/docs/clients/restful-api/task/) 等 REST API | | 驱动:Neo4j Bolt driver | [hugegraph-client](/cn/docs/clients/hugegraph-client/)(`CypherManager`)或任意 HTTP 客户端 | | 事务边界在 Cypher 语句内 | 每次请求一个语句;图到图的数据迁移使用 [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/)(首选 —— 见下文),基于文件的批量导入使用 [HugeGraph Loader](/cn/docs/quickstart/toolchain/hugegraph-loader/) | @@ -58,11 +59,18 @@ weight: 4 - [HugeGraph Source](https://seatunnel.apache.org/docs/3.0.0/connectors/source/HugeGraph/) 为 3.0.0 新增(schema 自动发现、多标签/并行读取),使 HugeGraph 的导出与迁移工作流成为可能。 - 将 Neo4j 属性映射为 HugeGraph PropertyKey,并在导入前先定好顶点 ID 策略:用 - `idStrategy = "PRIMARY_KEY"` 加 `idFields` 指定 Neo4j 业务键,边的端点也通过这些键字段表达; - 或用 `idStrategy = "CUSTOMIZE_STRING"` 保留 Neo4j 节点 id。第 2 步预创建的标签必须使用同一策略—— - 自动创建不会把已有的 `PRIMARY_KEY` 标签改为 `CUSTOMIZE_STRING`——而当 Sink 的 `mappings` 配置 - 负责创建 schema 时,第 2 步可省略。先导入顶点、后导入边。以上能力均有文档记载,但这里没有完整跑通 + 将 Neo4j 属性映射为 HugeGraph PropertyKey,并在导入前先定好顶点 ID 策略。Sink 对除 `AUTOMATIC` + 之外的每种顶点策略都要求 `idFields`,边映射还需要分别设置 `sourceConfig.idFields` 与 + `targetConfig.idFields`,因此 Neo4j 查询必须返回承载 ID 的字段: + - `idStrategy = "PRIMARY_KEY"`:在 `idFields` 中放入 Neo4j 业务键,边的端点也通过这些键字段表达。 + - `idStrategy = "CUSTOMIZE_STRING"`:仅选择它并不能保留 Neo4j 节点 id。请让 Neo4j 查询把要保留的 id + 作为单独一列返回(用 `AS node_id` 等别名),在 Source 的 `schema.fields` 中声明该字段(必须与查询返回的字段一致), + 把顶点的 `idFields` 设为该字段,并在 `sourceConfig.idFields` 与 `targetConfig.idFields` 中映射对应的边端点字段。 + + 第 2 步预创建的标签必须使用同一策略——自动创建不会把已有的 `PRIMARY_KEY` 标签改为 `CUSTOMIZE_STRING`。 + Sink 的 `mappings` 配置可以创建缺失的 PropertyKey、VertexLabel 和 EdgeLabel 定义,因此使用它时第 2 步中的这三类 + 定义可省略;但它不会创建 IndexLabel,查询所依赖的索引仍须单独创建(见上文“需要改变习惯的部分”表)。 + 先导入顶点、后导入边。以上能力均有文档记载,但这里没有完整跑通 一次 Neo4j → HugeGraph 迁移 —— 在把示例当作已验证之前,请先用你自己的数据验证。 4. **灰度切换**:Cypher 能表达的查询保持不动, translator 不支持的改写为 Gremlin(等价写法见 [对照表](/cn/docs/language/hugegraph-cypher/#等价的-gremlin-写法))。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index 8eab8cd72c..a8479498b1 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -106,6 +106,13 @@ three forms. The two-vertex shorthand `CREATE (a)-[:knows]->(b)` was verified in execution error reporting that the primary keys must be set, while single-vertex `CREATE` on that label succeeds. On `PRIMARY_KEY` schemas, issue the two `CREATE` statements separately or use the `AUTOMATIC` id strategy for this form. +Two guide examples depend on the schema. The range-predicate read (`WHERE n.age > 30`) needs the `RANGE` index on `age` +declared in the fixture schema above; the `scripts/example.groovy` schema has only `SECONDARY` indexes on `person` +(`city`, and `age` with `city`), so a range comparison on `age` there is rejected with a "not indexed" error until a +`RANGE` index exists. The create, update and delete examples were renamed afterwards to `alice`, `bob` and `carol` because +`scripts/example.groovy` already seeds `marko`, `vadas`, `josh` and `peter`, and on a `PRIMARY_KEY` label a `CREATE` with a seeded +name replaces that vertex; the rename changes only data values and was not run as a separate verification. + The standalone code change is in [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), which was merged into Apache `master` on 2026-10-08 as [`5039e5b`](https://github.com/apache/hugegraph/commit/5039e5b67d26ea305b8509d3a414877749baaebb); diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index 6643580798..c1cc1f99c1 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -47,8 +47,15 @@ ResultSet resultSet = hugeClient.cypher().execute("MATCH (n:person) RETURN n.nam ### Basic examples The examples below assume a graph with `person` vertices (`name`, `age`, `city` properties) and `knows` edges. -They assume the labels declare `nullableKeys("age", "city")` on `person` and nullable properties on `knows` — -for example the schema in `scripts/example.groovy` modified with those nullable keys. On a schema without them +They assume the labels declare `nullableKeys("age", "city")` on `person` and nullable properties on `knows`, and that +`person.age` has a `RANGE` index — for example the schema in `scripts/example.groovy` modified with those nullable keys +plus `schema.indexLabel("personByAge").onV("person").by("age").range().ifNotExist().create()`. A property predicate in +`WHERE` must be covered by an index: `scripts/example.groovy` indexes `person.city` and `(age, city)` with `SECONDARY` indexes only, +so a range comparison such as `n.age > 30` is rejected with a "not indexed" error until the `RANGE` index exists. +If you load `scripts/example.groovy` first, note that it already seeds the `person` vertices `marko`, `vadas`, `josh` and `peter`; +because the `person` label uses the `PRIMARY_KEY` id strategy, a `CREATE` with one of those names replaces the seeded vertex, +so the create, update and delete examples below use names that the sample data does not contain (`alice`, `bob`, `carol`), +or run them on an empty graph. On a schema without the nullable keys (the released default marks `age` and `city` non-null on `person`), the create and update examples below fail the non-null property check: set every non-null property in each statement, or declare the labels with `nullableKeys` first. If the `person` label uses the `PRIMARY_KEY` id strategy (as it does in `scripts/example.groovy`), the two-vertex @@ -83,22 +90,22 @@ RETURN b.name AS friend ```cypher // Create a vertex -CREATE (n:person {name: 'josh', age: 32, city: 'beijing'}) +CREATE (n:person {name: 'alice', age: 32, city: 'beijing'}) ``` ```cypher // Create two vertices, then an edge between them (send each statement as its own request) -CREATE (:person {name: 'peter'}) -CREATE (:person {name: 'lop'}) +CREATE (:person {name: 'bob'}) +CREATE (:person {name: 'carol'}) MATCH (a:person), (b:person) -WHERE a.name = 'peter' AND b.name = 'lop' +WHERE a.name = 'bob' AND b.name = 'carol' CREATE (a)-[:knows]->(b) ``` #### Update — SET / REMOVE ```cypher -MATCH (n:person) WHERE n.name = 'josh' +MATCH (n:person) WHERE n.name = 'alice' SET n.age = 33 REMOVE n.city ``` @@ -108,13 +115,13 @@ REMOVE n.city ```cypher // Delete an edge MATCH (a:person)-[r:knows]->(b:person) -WHERE a.name = 'peter' AND b.name = 'lop' +WHERE a.name = 'bob' AND b.name = 'carol' DELETE r ``` ```cypher // Delete a vertex and all its edges -MATCH (n:person) WHERE n.name = 'josh' +MATCH (n:person) WHERE n.name = 'alice' DETACH DELETE n ``` @@ -148,7 +155,7 @@ Tip: `EXPLAIN MATCH (n:person) RETURN n` is parsed with the `EXPLAIN` option, an Cypher support in HugeGraph is bounded by the transpiler layer, which is based on openCypher 9 era tooling. Known gaps: -- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding is inlined as `null` rather than failing, and the result depends on the expression: a predicate such as `WHERE n.name = $name` matches no rows, `RETURN $value AS value` still returns a row holding `null`, and a write stores a null value. Sanitize/escape values on the client side before interpolating them into the statement. On the tested tree with [#3289](https://github.com/apache/hugegraph/pull/3289) merged, this changes: a missing binding is an execution error for every request form, including `GET ?cypher=` and raw-body `POST` — the server always attaches a parameters map and rejects unresolved `$param` references. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. +- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding is inlined as `null` rather than failing, and the result depends on the expression: a predicate such as `WHERE n.name = $name` matches no rows, `RETURN $value AS value` still returns a row holding `null`. A write with a missing binding does not reliably store a null value: depending on the statement, `SET n.prop = $missing` removes the existing property, `CREATE (n:label {prop: $missing})` stores the translator's null marker string `" cypher.null"` in a text property, and the same `CREATE` on a non-text property, or `SET` on a non-nullable property, fails with an error. Sanitize/escape values on the client side before interpolating them into the statement. On the tested tree with [#3289](https://github.com/apache/hugegraph/pull/3289) merged, this changes: a missing binding is an execution error for every request form, including `GET ?cypher=` and raw-body `POST` — the server always attaches a parameters map and rejects unresolved `$param` references. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. - **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET` and `NOT ... IN` do translate, but they are not verified end-to-end on HugeGraph. The development change verifies two whole-string `=~` matching cases on computed strings; broader regex coverage remains unverified — see the [compatibility notes](/docs/language/cypher-compatibility/). - **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. - **Single statement per request** — multi-statement scripts are not supported; send one statement per call. diff --git a/content/en/docs/language/migrate-from-neo4j.md b/content/en/docs/language/migrate-from-neo4j.md index a184bcd75e..850cdd4aa9 100644 --- a/content/en/docs/language/migrate-from-neo4j.md +++ b/content/en/docs/language/migrate-from-neo4j.md @@ -20,7 +20,7 @@ development-tree verification record and | Neo4j concept | HugeGraph equivalent | |---|---| | Property graph model (nodes / relationships / properties) | Same — vertex labels / edge labels / properties | -| Core Cypher: `MATCH`/`WHERE`/`RETURN`/`CREATE`/`SET`/`DELETE` | Works as-is (REST `/cypher` endpoint or Java client `CypherManager`) | +| Core Cypher: `MATCH`/`WHERE`/`RETURN`/`CREATE`/`SET`/`DELETE` | Works as-is (REST `/cypher` endpoint or Java client `CypherManager`), subject to the schema and index rules below | | Simple aggregations (`count`/`sum`/`min`/`max`/`avg`) | Works as-is | | Traversal-heavy queries | Gremlin traversals or the [traverser REST APIs](/docs/clients/restful-api/traverser/) (k-out, shortest path, personalrank, ...) | @@ -30,7 +30,8 @@ development-tree verification record and |---|---| | `CREATE INDEX` / `CREATE CONSTRAINT` | Create indexes/constraints through the [IndexLabel REST API](/docs/clients/restful-api/indexlabel/); Cypher carries no DDL | | Implicit schema (add properties freely) | **Strong schema**: define VertexLabel / EdgeLabel / PropertyKey before writing data | -| Parameterized queries `$param` | Released versions send the raw statement only — a missing binding is inlined as `null` instead of failing (a predicate on it matches no rows), so validate values client-side; JSON-bound parameters are available on `master` after [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), with a fixed limit of 16 top-level bindings | +| Property predicates in `WHERE` need no index | A `WHERE` predicate on a property must be covered by an index: create a `SECONDARY` or `RANGE` IndexLabel first, and use `RANGE` for comparisons such as `>` or `<`. Without a covering index the request returns `status.code` 400 with a "not indexed" error | +| Parameterized queries `$param` | Released versions send the raw statement only — a missing binding is inlined as `null` instead of failing (a predicate on it matches no rows, and a write does not reliably store `null`: `SET` removes the property, `CREATE` can store the marker string `" cypher.null"` or fail), so validate values client-side; JSON-bound parameters are available on `master` after [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), with a fixed limit of 16 top-level bindings | | `CALL dbms.*` / `CALL algo.*` procedures | Equivalent capabilities live in the [traverser](/docs/clients/restful-api/traverser/), [task](/docs/clients/restful-api/task/), and other REST APIs | | Driver: Neo4j Bolt driver | [hugegraph-client](/docs/clients/hugegraph-client/) (`CypherManager`) or any HTTP client | | Transaction boundaries inside a Cypher statement | One statement per request; graph-to-graph data migration uses [Apache SeaTunnel 3.0.0](https://seatunnel.apache.org/download/) (preferred — see below), file-based bulk loads use the [HugeGraph Loader](/docs/quickstart/toolchain/hugegraph-loader/) | @@ -70,12 +71,22 @@ The latest published release is 1.7.0 as of 2026-10-09; the merged JSON-bound re and migration workflows. Map Neo4j properties to HugeGraph PropertyKeys and pick the vertex ID strategy - before importing: use `idStrategy = "PRIMARY_KEY"` with a Neo4j business key in - `idFields` and express edge endpoints through those same key fields, or - `idStrategy = "CUSTOMIZE_STRING"` to keep the Neo4j node id. Labels you - pre-created in step 2 must use that same strategy — automatic creation does not - convert an existing `PRIMARY_KEY` label into `CUSTOMIZE_STRING` — and step 2 is - optional when the Sink `mappings` configuration creates the schema. Load vertices + before importing. The Sink requires `idFields` for every vertex strategy other than + `AUTOMATIC`, and edge mappings need separate `sourceConfig.idFields` and + `targetConfig.idFields`, so the Neo4j query must return the field that carries the ID: + - `idStrategy = "PRIMARY_KEY"`: put a Neo4j business key in `idFields` and express edge + endpoints through those same key fields. + - `idStrategy = "CUSTOMIZE_STRING"`: this alone does not keep the Neo4j node id. Make the + Neo4j query return the id you want to keep as its own column (aliased, for example `AS node_id`), + declare that field in the Source `schema.fields` (it must match the fields the query + returns), set the vertex `idFields` to it, and map the matching edge endpoint fields + in `sourceConfig.idFields` and `targetConfig.idFields`. + + Labels you pre-created in step 2 must use that same strategy — automatic creation does not + convert an existing `PRIMARY_KEY` label into `CUSTOMIZE_STRING`. The Sink `mappings` + configuration can create the missing PropertyKey, VertexLabel and EdgeLabel definitions, so + those three parts of step 2 are optional when you use it; it does not create IndexLabels, so + create any index your queries rely on (see the habits table above) separately. Load vertices before edges. These capabilities are documented, but a complete Neo4j → HugeGraph migration has not been run end-to-end here — validate examples against your own data before treating them as tested. From 70a12782e6c0f1db515687a513c4140bfd3f4054 Mon Sep 17 00:00:00 2001 From: n24q02m Date: Wed, 14 Oct 2026 08:42:38 +0700 Subject: [PATCH 17/17] fix: rewrap Cypher pages at 160 characters Co-Authored-By: Claude Opus 5.5 (1M context) --- content/cn/docs/language/hugegraph-cypher.md | 23 ++++++---- .../en/docs/language/cypher-compatibility.md | 6 ++- content/en/docs/language/hugegraph-cypher.md | 42 +++++++++++++++---- .../en/docs/language/migrate-from-neo4j.md | 3 +- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/content/cn/docs/language/hugegraph-cypher.md b/content/cn/docs/language/hugegraph-cypher.md index a8cca634b6..389c8d67b2 100644 --- a/content/cn/docs/language/hugegraph-cypher.md +++ b/content/cn/docs/language/hugegraph-cypher.md @@ -6,9 +6,11 @@ weight: 2 ### 概述 -HugeGraph 支持 [Cypher](https://opencypher.org/) —— 最初由 Neo4j 创建、并由 [openCypher](https://github.com/opencypher/openCypher) 标准化的声明式图查询语言。Gremlin 是命令式的遍历语言,而 Cypher 只需描述想要的图模式(`MATCH`、`WHERE`、`RETURN`),由引擎决定如何执行。 +HugeGraph 支持 [Cypher](https://opencypher.org/) —— 最初由 Neo4j 创建、并由 [openCypher](https://github.com/opencypher/openCypher) 标准化的声明式图查询语言。Gremlin 是命令式的遍历语言,而 Cypher +只需描述想要的图模式(`MATCH`、`WHERE`、`RETURN`),由引擎决定如何执行。 -HugeGraph 通过 [cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) 转译器将 Cypher 语句翻译为 Gremlin,再在 TinkerPop 技术栈上执行。因此 HugeGraph 的 Cypher 能力覆盖转译器所实现的 openCypher 9 语法面 —— 详见下文[已知限制](#已知限制)。 +HugeGraph 通过 [cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) 转译器将 Cypher 语句翻译为 Gremlin,再在 TinkerPop 技术栈上执行。因此 HugeGraph 的 Cypher +能力覆盖转译器所实现的 openCypher 9 语法面 —— 详见下文[已知限制](#已知限制)。 ### 何时用 Cypher、何时用 Gremlin @@ -29,7 +31,8 @@ GET /graphspaces/{graphspace}/graphs/{graph}/cypher?cypher={statement} POST /graphspaces/{graphspace}/graphs/{graph}/cypher ``` -该端点始终要求 `Authorization` 头(`Basic` 或 `Bearer`),即使服务端未开启认证 —— 凭据会被转发给 Gremlin Server。`Basic` 凭据必须使用 URL 安全的 Base64 编码(用 `-` 和 `_` 代替 `+` 和 `/`),且密码不能包含 `:`;无法满足这两个条件的账号请改用 `Bearer`。完整的请求/响应格式见 [Cypher REST API 参考](/cn/docs/clients/restful-api/cypher/)。 +该端点始终要求 `Authorization` 头(`Basic` 或 `Bearer`),即使服务端未开启认证 —— 凭据会被转发给 Gremlin Server。`Basic` 凭据必须使用 URL 安全的 Base64 编码(用 `-` 和 `_` 代替 `+` 和 `/`),且密码不能包含 `:`; +无法满足这两个条件的账号请改用 `Bearer`。完整的请求/响应格式见 [Cypher REST API 参考](/cn/docs/clients/restful-api/cypher/)。 示例: @@ -147,16 +150,22 @@ MATCH (n:person) RETURN n.city AS city, count(*) AS cnt ORDER BY cnt DESC | `MATCH (n) DETACH DELETE n` | `g.V().drop()` | | `MATCH (n:person) RETURN count(n)` | `g.V().hasLabel('person').count()` | -提示:`EXPLAIN MATCH (n:person) RETURN n` 会以 `EXPLAIN` 选项解析,翻译后的 Gremlin 预期出现在 `result.data[0].translation` 中 —— 这是转译层行为,尚未在服务器上端到端验证(见[兼容性说明](/cn/docs/language/cypher-compatibility/))。它仍是起草上表等价写法的最快方式。`PROFILE` 不受支持。 +提示:`EXPLAIN MATCH (n:person) RETURN n` 会以 `EXPLAIN` 选项解析,翻译后的 Gremlin 预期出现在 `result.data[0].translation` 中 —— 这是转译层行为,尚未在服务器上端到端验证(见 +[兼容性说明](/cn/docs/language/cypher-compatibility/))。它仍是起草上表等价写法的最快方式。`PROFILE` 不受支持。 ### 已知限制 HugeGraph 的 Cypher 能力受转译层约束,该层基于 openCypher 9 时代的工具链。已知缺口: -- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被内联为 `null`,结果取决于表达式:`WHERE n.name = $name` 这类谓词匹配不到行,`RETURN $value AS value` 仍会返回一行 `null`。缺失绑定的写入并不能可靠地存入 null 值:视语句而定,`SET n.prop = $missing` 会移除已有属性,`CREATE (n:label {prop: $missing})` 会在文本属性中存入转译库的 null 标记字符串 `" cypher.null"`,而对非文本属性执行同样的 `CREATE`,或对非空属性执行 `SET`,则会报错。请在客户端先对值做转义/净化再拼接到语句中。在合入 [#3289](https://github.com/apache/hugegraph/pull/3289) 后的 +- **已发布版本不支持参数化查询** —— API 只接受原始语句字符串。使用 `$param` 的语句不会报错:缺失的绑定会被内联为 `null`,结果取决于表达式:`WHERE n.name = $name` 这类谓词匹配不到行,`RETURN $value AS value` 仍会返回一行 `null`。 + 缺失绑定的写入并不能可靠地存入 null 值:视语句而定,`SET n.prop = $missing` 会移除已有属性,`CREATE (n:label {prop: $missing})` 会在文本属性中存入转译库的 null 标记字符串 `" cypher.null"`,而对非文本属性执行同样的 + `CREATE`,或对非空属性执行 `SET`,则会报错。请在客户端先对值做转义/净化再拼接到语句中。在合入 [#3289](https://github.com/apache/hugegraph/pull/3289) 后的 测试栈上情况改变:缺失的绑定对所有请求形式都是执行错误,包括 `GET ?cypher=` 与原始文本 -`POST`——服务器总是附带参数表并拒绝未解析的 `$param` 引用。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)已通过合入 `master` 的 [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 -- **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证。开发改动验证了计算字符串上的两个 `=~` 全字符串匹配用例,更广泛的正则覆盖仍未验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 +`POST`——服务器总是附带参数表并拒绝未解析的 `$param` 引用。JSON 绑定参数(`{"cypher": ..., "parameters": {...}}`)已通过合入 `master` 的 +[ASF PR #3289](https://github.com/apache/hugegraph/pull/3289) 引入,承接原 [PR #238](https://github.com/hugegraph/hugegraph/pull/238);已验证的请求契约见 +[开发版兼容性记录](/cn/docs/language/cypher-compatibility/)。 +- **子句覆盖不完整** —— 部分 openCypher 结构无法翻译(例如 map projection、部分 `datetime()` 函数)。不支持的结构会在翻译阶段报错。`MERGE ... ON CREATE SET`、`NOT ... IN` 等结构可以翻译,但尚未在 HugeGraph 上端到端验证。 + 开发改动验证了计算字符串上的两个 `=~` 全字符串匹配用例,更广泛的正则覆盖仍未验证 —— 见[兼容性说明](/cn/docs/language/cypher-compatibility/)。 - **不支持 `CALL` 过程** —— HugeGraph 的图算法(最短路径、k-out、personalrank 等)未暴露为 Cypher 过程;请改用 [traverser REST API](/cn/docs/clients/restful-api/traverser/) 或 Gremlin。 - **每次请求仅一条语句** —— 不支持多语句脚本,请每次调用发送一条语句。 diff --git a/content/en/docs/language/cypher-compatibility.md b/content/en/docs/language/cypher-compatibility.md index a8479498b1..5d90a38a5e 100644 --- a/content/en/docs/language/cypher-compatibility.md +++ b/content/en/docs/language/cypher-compatibility.md @@ -36,7 +36,8 @@ The endpoint is `/graphspaces/{graphspace}/graphs/{graph}/cypher`. General usage | `POST text/plain` with any body | No | Rejected with HTTP 415 | `testRejectPlainTextPost` | | `POST application/json` with a JSON object | No — introduced by [#3289](https://github.com/apache/hugegraph/pull/3289) | Query and bindings are sent separately | `testParameters` | -The JSON object form below is therefore **not available in any released HugeGraph version**; it describes the merged change on `master` (the 1.8.0 development line). On released versions a statement using `$param` runs with the missing binding inlined as `null`; whether it returns rows +The JSON object form below is therefore **not available in any released HugeGraph version**; it describes the merged change on `master` (the 1.8.0 development +line). On released versions a statement using `$param` runs with the missing binding inlined as `null`; whether it returns rows depends on the expression (`WHERE n.name = $name` matches nothing, `RETURN $value AS value` returns a row holding `null`) — see [Known limitations](/docs/language/hugegraph-cypher/#known-limitations). @@ -133,7 +134,8 @@ The compatibility note at that fixed commit contains the verification record and Test sources: [`CypherApiTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/CypherApiTest.java), [`CypherClientTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java), -and [`CypherOpProcessorTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java). +and +[`CypherOpProcessorTest`](https://github.com/apache/hugegraph/blob/8d06ad3b18fbd18807cf545184d07e6fec0c55b4/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessorTest.java). The earlier verification on [`e62c961`](https://github.com/apache/hugegraph/commit/e62c961e00221569d4f955abbadf60faee45b283) remains at diff --git a/content/en/docs/language/hugegraph-cypher.md b/content/en/docs/language/hugegraph-cypher.md index c1cc1f99c1..8bd5a245bf 100644 --- a/content/en/docs/language/hugegraph-cypher.md +++ b/content/en/docs/language/hugegraph-cypher.md @@ -6,9 +6,13 @@ weight: 2 ### Overview -HugeGraph supports [Cypher](https://opencypher.org/), the declarative graph query language originally created by Neo4j and standardized as [openCypher](https://github.com/opencypher/openCypher). While Gremlin is an imperative traversal language, Cypher lets you describe the graph pattern you want (`MATCH`, `WHERE`, `RETURN`) and lets the engine decide how to execute it. +HugeGraph supports [Cypher](https://opencypher.org/), the declarative graph query language originally created by Neo4j and standardized as +[openCypher](https://github.com/opencypher/openCypher). While Gremlin is an imperative traversal language, Cypher lets you describe the graph pattern you want +(`MATCH`, `WHERE`, `RETURN`) and lets the engine decide how to execute it. -HugeGraph executes Cypher by translating the statement to Gremlin through the [cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) transpiler, then running the resulting traversal on the TinkerPop stack. This means Cypher support in HugeGraph covers the openCypher 9 surface that the transpiler implements — see [Known limitations](#known-limitations) below. +HugeGraph executes Cypher by translating the statement to Gremlin through the [cypher-for-gremlin](https://github.com/opencypher/cypher-for-gremlin) transpiler, +then running the resulting traversal on the TinkerPop stack. This means Cypher support in HugeGraph covers the openCypher 9 surface that the transpiler +implements — see [Known limitations](#known-limitations) below. ### When to use Cypher vs Gremlin @@ -29,7 +33,10 @@ GET /graphspaces/{graphspace}/graphs/{graph}/cypher?cypher={statement} POST /graphspaces/{graphspace}/graphs/{graph}/cypher ``` -The endpoint always requires an `Authorization` header (`Basic` or `Bearer`), even when server authentication is disabled — the credentials are forwarded to the Gremlin Server. `Basic` credentials must be encoded with URL-safe Base64 (`-` and `_` instead of `+` and `/`), and the password must not contain `:`; use `Bearer` for accounts that cannot meet either condition. See the [Cypher REST API reference](/docs/clients/restful-api/cypher/) for the full request/response format. +The endpoint always requires an `Authorization` header (`Basic` or `Bearer`), even when server authentication is disabled — the credentials are forwarded to the +Gremlin Server. `Basic` credentials must be encoded with URL-safe Base64 (`-` and `_` instead of `+` and `/`), and the password must not contain `:`; use +`Bearer` for accounts that cannot meet either condition. See the [Cypher REST API reference](/docs/clients/restful-api/cypher/) for the full request/response +format. Example: @@ -149,18 +156,34 @@ Every Cypher statement is translated to Gremlin internally. When a Cypher featur | `MATCH (n) DETACH DELETE n` | `g.V().drop()` | | `MATCH (n:person) RETURN count(n)` | `g.V().hasLabel('person').count()` | -Tip: `EXPLAIN MATCH (n:person) RETURN n` is parsed with the `EXPLAIN` option, and the translated Gremlin is expected in `result.data[0].translation` — translator-level behavior, not yet verified end-to-end on a server (see the [compatibility notes](/docs/language/cypher-compatibility/)). It remains the quickest way to draft the equivalent traversal for the table above. `PROFILE` is not supported. +Tip: `EXPLAIN MATCH (n:person) RETURN n` is parsed with the `EXPLAIN` option, and the translated Gremlin is expected in `result.data[0].translation` — +translator-level behavior, not yet verified end-to-end on a server (see the [compatibility notes](/docs/language/cypher-compatibility/)). It remains the +quickest way to draft the equivalent traversal for the table above. `PROFILE` is not supported. ### Known limitations Cypher support in HugeGraph is bounded by the transpiler layer, which is based on openCypher 9 era tooling. Known gaps: -- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding is inlined as `null` rather than failing, and the result depends on the expression: a predicate such as `WHERE n.name = $name` matches no rows, `RETURN $value AS value` still returns a row holding `null`. A write with a missing binding does not reliably store a null value: depending on the statement, `SET n.prop = $missing` removes the existing property, `CREATE (n:label {prop: $missing})` stores the translator's null marker string `" cypher.null"` in a text property, and the same `CREATE` on a non-text property, or `SET` on a non-nullable property, fails with an error. Sanitize/escape values on the client side before interpolating them into the statement. On the tested tree with [#3289](https://github.com/apache/hugegraph/pull/3289) merged, this changes: a missing binding is an execution error for every request form, including `GET ?cypher=` and raw-body `POST` — the server always attaches a parameters map and rejects unresolved `$param` references. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. -- **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET` and `NOT ... IN` do translate, but they are not verified end-to-end on HugeGraph. The development change verifies two whole-string `=~` matching cases on computed strings; broader regex coverage remains unverified — see the [compatibility notes](/docs/language/cypher-compatibility/). -- **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. +- **No parameterized queries in released versions** — the API accepts a raw statement string only. A statement using `$param` still runs: a missing binding is + inlined as `null` rather than failing, and the result depends on the expression: a predicate such as `WHERE n.name = $name` matches no rows, + `RETURN $value AS value` still returns a row holding `null`. A write with a missing binding does not reliably store a null value: depending on the statement, + `SET n.prop = $missing` removes the existing property, `CREATE (n:label {prop: $missing})` stores the translator's null marker string `" cypher.null"` in a + text property, and the same `CREATE` on a non-text property, or `SET` on a non-nullable property, fails with an error. Sanitize/escape values on the client + side before interpolating them into the statement. On the tested tree with [#3289](https://github.com/apache/hugegraph/pull/3289) merged, this changes: a + missing binding is an execution error for every request form, including `GET ?cypher=` and raw-body `POST` — the server always attaches a parameters map and + rejects unresolved `$param` references. JSON-bound parameters (`{"cypher": ..., "parameters": {...}}`) are available on `master` after the merged + [ASF PR #3289](https://github.com/apache/hugegraph/pull/3289), carried over from [PR #238](https://github.com/hugegraph/hugegraph/pull/238); see the + [development compatibility record](/docs/language/cypher-compatibility/) for the tested request contract. +- **Partial clause coverage** — some openCypher constructs are not translated (for example map projections and certain `datetime()` functions). Unsupported + constructs fail at translation time with an error from the transpiler. Constructs such as `MERGE ... ON CREATE SET` and `NOT ... IN` do translate, but they + are not verified end-to-end on HugeGraph. The development change verifies two whole-string `=~` matching cases on computed strings; broader regex coverage + remains unverified — see the [compatibility notes](/docs/language/cypher-compatibility/). +- **No `CALL` procedures** — HugeGraph graph algorithms (shortest path, k-out, personalrank, etc.) are not exposed as Cypher procedures; use the + [traverser REST APIs](/docs/clients/restful-api/traverser/) or Gremlin instead. - **Single statement per request** — multi-statement scripts are not supported; send one statement per call. -When a statement fails translation, the response `status.message` contains the transpiler error. If you hit a gap, the Gremlin equivalent is the supported fallback. +When a statement fails translation, the response `status.message` contains the transpiler error. If you hit a gap, the Gremlin equivalent is the supported +fallback. ### Further reading @@ -168,4 +191,5 @@ When a statement fails translation, the response `status.message` contains the t - [Gremlin Query Language](/docs/language/hugegraph-gremlin/) - [openCypher project](https://opencypher.org/) — language specification and resources -The translator’s historical TCK percentage is not a HugeGraph end-to-end compatibility rate; no measured overall HugeGraph Cypher percentage is established here. +The translator’s historical TCK percentage is not a HugeGraph end-to-end compatibility rate; no measured overall HugeGraph Cypher percentage is established +here. diff --git a/content/en/docs/language/migrate-from-neo4j.md b/content/en/docs/language/migrate-from-neo4j.md index 850cdd4aa9..9a2378bc96 100644 --- a/content/en/docs/language/migrate-from-neo4j.md +++ b/content/en/docs/language/migrate-from-neo4j.md @@ -107,4 +107,5 @@ The latest published release is 1.7.0 as of 2026-10-09; the merged JSON-bound re [equivalents table](/docs/language/hugegraph-cypher/#gremlin-equivalents); schema DDL and `CALL` procedures map to REST APIs instead. -The translator’s historical TCK percentage is not a HugeGraph end-to-end compatibility rate; no measured overall HugeGraph Cypher percentage is established here. +The translator’s historical TCK percentage is not a HugeGraph end-to-end compatibility rate; no measured overall HugeGraph Cypher percentage is established +here.