imbajin commented on code in PR #499:
URL: https://github.com/apache/hugegraph-doc/pull/499#discussion_r4314264095


##########
content/en/docs/language/migrate-from-neo4j.md:
##########
@@ -0,0 +1,111 @@
+---
+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
+[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
+development-tree verification record 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`), 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, ...) |
+
+### Habits you need to change
+
+| In Neo4j | In HugeGraph |
+|---|---|
+| `CREATE INDEX` / `CREATE CONSTRAINT` | Create property indexes through the 
[IndexLabel REST API](/docs/clients/restful-api/indexlabel/); uniqueness 
constraints map to `UNIQUE` IndexLabels (which reject duplicates with a 
conflict error). Node keys map to non-nullable keys plus a composite `UNIQUE` 
index; a `UNIQUE` index cannot include all primary keys of a `PRIMARY_KEY` 
label (the server rejects it), so to keep duplicate rejection use 
`CUSTOMIZE_STRING` keyed on the Neo4j node id with a `UNIQUE` index on the 
business key. Property existence constraints map to non-nullable keys on 
[VertexLabels](/docs/clients/restful-api/vertexlabel/) or 
[EdgeLabels](/docs/clients/restful-api/edgelabel/). Note that `primary_keys` 
defines vertex identity rather than a constraint—a duplicate `CREATE` 
overwrites instead of failing |
+| Implicit schema (add properties freely) | **Strong schema**: define 
VertexLabel / EdgeLabel / PropertyKey before writing data |
+| Property predicates in `WHERE` need no index | The starting vertex lookup in 
`WHERE` needs a covering index unless it is an equality on every primary key of 
the label: 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/) |
+
+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
+   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.
+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)
+   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/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`.
+   - [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 and pick the vertex ID 
strategy
+   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

Review Comment:
   ⚠️ Important: Blocking: no. Summary: Auto-created EdgeLabels default to 
`SINGLE` when SeaTunnel 3.0.0 mappings omit `frequency`, so parallel Neo4j 
relationships with the same type and endpoints cannot retain distinct edge 
identities. Please warn about this and specify `frequency = "MULTIPLE"` with a 
stable relationship `sortKeys` in both language guides. Evidence: SeaTunnel 
3.0.0 `SchemaManager` defaults a missing frequency to `SINGLE` and requires 
sort keys for `MULTIPLE` (commit 543f2a5); HugeGraph edge IDs include sort keys.



##########
content/en/docs/language/hugegraph-cypher.md:
##########
@@ -0,0 +1,198 @@
+---
+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
+```
+
+On 1.2.0 to 1.7.0, the endpoint always requires an `Authorization` header 
(`Basic` or `Bearer`), even when server authentication is disabled —
+the credentials are forwarded to the Gremlin Server. On those versions `Basic` 
credentials must be encoded with URL-safe Base64 (`-` and `_` instead
+of `+` and `/`), and the password must not contain `:`. On `master` (1.8.0+), 
authentication is optional when server auth is disabled
+([#3366](https://github.com/apache/hugegraph/pull/3366)), `Basic` credentials 
use standard RFC 4648 Base64 (as sent by `curl -u`,
+[#3290](https://github.com/apache/hugegraph/pull/3290)), and `:` in passwords 
is supported.
+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.
+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` on the starting vertex needs a covering index unless it is an 
equality on every primary key of the label:
+`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
+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
+
+```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'
+RETURN b.name AS friend
+```
+
+#### Create — CREATE
+
+```cypher
+// Create a vertex
+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: 'bob'})
+CREATE (:person {name: 'carol'})
+MATCH (a:person), (b:person)
+WHERE a.name = 'bob' AND b.name = 'carol'
+CREATE (a)-[:knows]->(b)
+```
+
+#### Update — SET / REMOVE
+
+```cypher
+MATCH (n:person) WHERE n.name = 'alice'
+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 = 'bob' AND b.name = 'carol'
+DELETE r
+```
+
+```cypher
+// Delete a vertex and all its edges
+MATCH (n:person) WHERE n.name = 'alice'
+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
+```
+
+### 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()` |
+
+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.
+- **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

Review Comment:
   ⚠️ Important: Blocking: no. Summary: This only says translation failures 
appear in `status.message`, but current master also returns stable 
`status.attributes.errors` entries with `code`, `message` and `hint` after 
#3259. Please document this machine-readable error shape in the REST API 
reference, or scope this statement to the pinned pre-#3259 commit. Evidence: 
Current `CypherModel.failOf()` populates `status.attributes.errors`, and 
`CypherClient` maps failures through `CypherErrorMapper`; merge #3259 is 
a0aae8e7.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to