bitflicker64 commented on code in PR #541:
URL: https://github.com/apache/hugegraph-doc/pull/541#discussion_r4314135356


##########
content/en/docs/guides/gremlin-migration-3.8.md:
##########
@@ -0,0 +1,189 @@
+---
+title: "HugeGraph 1.8.0 Gremlin Migration & Compatibility Guide"
+linkTitle: "1.8 Gremlin & TinkerPop Migration"
+description: "Comprehensive guide to breaking changes, high-frequency syntax 
rewrites, configuration migrations, and complete compatibility references from 
TinkerPop 3.5 to 3.8 in HugeGraph 1.8.0."
+weight: 9
+---
+
+HugeGraph 1.8.0 upgrades its underlying graph traversal and query framework 
from Apache TinkerPop 3.5.1 to **TinkerPop 3.8.1**, requires **Java 17** for 
Server and builds, and updates the script engine to **Groovy 4.0.25**.
+
+While bringing substantial performance optimizations and specification 
alignments, this upgrade introduces several language-level breaking changes. 
This guide highlights the **most critical and frequently used syntax changes** 
with recommended rewrites to ensure seamless migration. Edge cases and 
lower-level protocol details are organized in the [Full Compatibility 
Reference](#full-compatibility-reference) at the end.
+
+> [!NOTE]
+> - This guide applies to upgrades from version 1.7.0 (or earlier) to 1.8.0.
+> - The **Groovy script engine** remains supported in 1.8.0, allowing existing 
multi-line scripts, variable definitions, and Java closures to continue 
functioning as expected.
+
+---
+
+## Top 6 High-Frequency Syntax and Behavioral Changes
+
+Among existing query scripts, the following 6 changes are the most common. 
**Failure to update these may cause query errors or silently return empty 
results.**
+
+### 1. `has(key, traversal)` Overload Removed (High Risk: Silent Empty Results)
+
+* **Impact**:
+  In TinkerPop 3.8.0, the `has(String, Traversal)` and `has(T, Traversal)` 
overloads were removed.
+  In the Groovy script engine, legacy code will not throw a compilation error; 
instead, it **silently falls back to `has(String, Object)`**, comparing the 
anonymous traversal object itself against vertex/edge properties. In practice, 
this **silently yields 0 results / empty sets**!
+* **Legacy Query**:
+  ```groovy
+  // Broken in 3.8: will not throw an error, but silently returns 0 results
+  g.V().has('age', __.is(gt(30)))
+  g.V().has(T.label, __.is('person'))
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // For simple scalar/predicate checks, pass predicates directly
+  g.V().has('age', gt(30))
+  g.V().hasLabel('person')
+  g.V().hasId('v-1')
+
+  // If passing property values into child traversals for complex filtering, 
use filter()
+  g.V().filter(__.values('age').is(gt(30)))
+  ```
+
+---
+
+### 2. `store()` Removed & `aggregate()` Scope Overload Removed
+
+* **Impact**:
+  - The `store('x')` step, previously used for lazy side-effect collection, 
has been completely removed (`No signature of method: store()`).
+  - The `aggregate(Scope, 'x')` overload with an explicit `Scope` (both 
`local` and `global`) has also been removed.
+* **Legacy Query**:
+  ```groovy
+  // Broken: store step removed
+  g.V().store('x').by('age').cap('x')
+
+  // Broken: aggregate(Scope, ...) overload removed
+  g.V().aggregate(local, 'x')
+  g.V().aggregate(global, 'x')
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // 1. Eager global collection (formerly global aggregate): use 
aggregate('x') directly
+  g.V().aggregate('x').by('age').cap('x')
+
+  // 2. Per-object / lazy collection (formerly store or local aggregate): wrap 
in local()
+  g.V().local(__.aggregate('x').by('age')).cap('x')
+  ```
+
+---
+
+### 3. Step `none()` Renamed to `discard()`
+
+* **Impact**:
+  The parameterless `none()` step was originally used to discard all incoming 
traversers (e.g., at the end of `choose()` or `coalesce()` branches). In 3.8.0, 
this step is renamed to **`discard()`**.
+  Meanwhile, 3.8 introduces a new collection predicate step `none(P)` 
(checking if no elements in a collection match predicate P). Calling 
parameterless `none()` in 3.8 triggers argument errors.
+* **Recommended Rewrite**:
+  ```groovy
+  // Legacy:
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.none()) // Error
+
+  // Rewritten: use discard()
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.discard())
+  ```
+
+---
+
+### 4. Strict Behavior for Missing Properties in `by()`
+
+* **Impact**:
+  TinkerPop 3.6+ unified missing value handling across `by()` modulators 
(removing previous default-null behaviors). In 3.8.1, when a property 
referenced by `by()` does not exist:
+  1. **Ordering `order().by('age')`**: Vertices missing `age` are 
**immediately filtered out** (previously they might sort first/last).
+  2. **Projection `project('name', 'age').by('name').by('age')`**: If `age` is 
missing, the returned Map **will not contain the `age` key at all** (previously 
returned `age: null`).
+  3. **Path `path().by('age')`**: If any vertex along the path misses `age`, 
the **entire path is dropped**.
+* **Recommended Rewrite**:
+  If your application requires preserving elements with explicit defaults 
(e.g., `null`), use `coalesce()` inside `by()`:
+  ```groovy
+  // Retain key 'age' with null when missing
+  g.V().project('name', 'age')
+    .by('name')
+    .by(__.coalesce(__.values('age'), __.constant(null)))
+
+  // Provide a typed default for sorting missing fields
+  g.V().order().by(__.coalesce(__.values('age'), __.constant(-1)), desc)
+  ```
+
+---
+
+### 5. `choose()` Semantics Alignment
+
+* **Impact**:
+  - **Single Branch Execution**: When multiple `option()` conditions match 
simultaneously, 3.8 **executes only the first matching branch** (legacy 
versions might execute all matching branches).
+  - **Default Pass-Through**: If the choice child traversal yields no values 
(e.g., property missing) or no `option()` matches, 3.8 **passes the input 
element through unchanged** by default (legacy versions often filtered it out).
+* **Recommended Rewrite**:
+  - To execute multiple matching branches, rewrite using `union()` combined 
with `filter()`.
+  - To filter out elements when no option matches or property is missing, 
explicitly supply `Pick.none` and `Pick.unproductive` branches:
+  ```groovy
+  // Discard unmatched and missing-property inputs
+  g.V().choose(__.values('age'))
+    .option(gt(30), __.values('name'))
+    .option(Pick.none, __.discard())
+    .option(Pick.unproductive, __.discard())
+  ```
+
+---
+
+### 6. Date Types and Time Difference Units
+
+* **Impact**:
+  - **Return Type**: Date steps such as `datetime()` and `dateAdd()` now 
return **`java.time.OffsetDateTime`** instead of `java.util.Date`.
+  - **Unit Change in `dateDiff()`**: The difference between two dates is now 
returned in **milliseconds** instead of seconds (e.g., 1 day difference is 
`86400000` ms instead of `86400` s).

Review Comment:
   Important: `datetime()`, `dateAdd()` and `dateDiff()` do not exist in 
TinkerPop 3.5.1, the version HugeGraph 1.7.0 ships (`tinkerpop.version` is 
3.5.1 in `hugegraph-server/pom.xml` at the 1.7.0 tag). On a 3.5.1 Groovy 
engine, `g.inject(new Date(86400000L)).dateDiff(new Date(0L))` fails with 
`MissingMethodException: No signature of method: ...dateDiff()`, and 
`datetime('2026-10-19T00:00:00Z')` fails the same way. No 1.7.0 script can have 
got a `java.util.Date` or a seconds value from these steps. Seconds to 
milliseconds and `Date` to `OffsetDateTime` are differences between 3.7 and 
3.8, not between 1.7.0 and 1.8.0. Because this section is listed as one of the 
six breaking changes, and the release notes repeat it under Key Breaking 
Changes (EN and CN line 22), 1.7 users are told to audit `dateDiff()` TTL 
checks they cannot have written. On 3.8.1 the steps do what the text says: 
`dateDiff` returns `86400000` and `datetime()` returns `OffsetDateTime`. So the 
facts are right, but they 
 describe new steps. Please move section 6 out of the Top 6 into a "new in 1.8" 
note, and drop the date bullet from the release-note breaking changes. Appendix 
1 (`mergeV`/`mergeE` are also absent in 3.5.1) and B14/B15 (`split()` and 
`asString()` are also absent in 3.5.1) have the same problem: list them as new 
steps, not as changed behaviour. The CN guide (lines 126-138 and 165-177) needs 
the same change.



##########
content/en/docs/guides/gremlin-migration-3.8.md:
##########
@@ -0,0 +1,189 @@
+---
+title: "HugeGraph 1.8.0 Gremlin Migration & Compatibility Guide"
+linkTitle: "1.8 Gremlin & TinkerPop Migration"
+description: "Comprehensive guide to breaking changes, high-frequency syntax 
rewrites, configuration migrations, and complete compatibility references from 
TinkerPop 3.5 to 3.8 in HugeGraph 1.8.0."
+weight: 9
+---
+
+HugeGraph 1.8.0 upgrades its underlying graph traversal and query framework 
from Apache TinkerPop 3.5.1 to **TinkerPop 3.8.1**, requires **Java 17** for 
Server and builds, and updates the script engine to **Groovy 4.0.25**.
+
+While bringing substantial performance optimizations and specification 
alignments, this upgrade introduces several language-level breaking changes. 
This guide highlights the **most critical and frequently used syntax changes** 
with recommended rewrites to ensure seamless migration. Edge cases and 
lower-level protocol details are organized in the [Full Compatibility 
Reference](#full-compatibility-reference) at the end.
+
+> [!NOTE]
+> - This guide applies to upgrades from version 1.7.0 (or earlier) to 1.8.0.
+> - The **Groovy script engine** remains supported in 1.8.0, allowing existing 
multi-line scripts, variable definitions, and Java closures to continue 
functioning as expected.
+
+---
+
+## Top 6 High-Frequency Syntax and Behavioral Changes
+
+Among existing query scripts, the following 6 changes are the most common. 
**Failure to update these may cause query errors or silently return empty 
results.**
+
+### 1. `has(key, traversal)` Overload Removed (High Risk: Silent Empty Results)
+
+* **Impact**:
+  In TinkerPop 3.8.0, the `has(String, Traversal)` and `has(T, Traversal)` 
overloads were removed.
+  In the Groovy script engine, legacy code will not throw a compilation error; 
instead, it **silently falls back to `has(String, Object)`**, comparing the 
anonymous traversal object itself against vertex/edge properties. In practice, 
this **silently yields 0 results / empty sets**!
+* **Legacy Query**:
+  ```groovy
+  // Broken in 3.8: will not throw an error, but silently returns 0 results
+  g.V().has('age', __.is(gt(30)))
+  g.V().has(T.label, __.is('person'))
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // For simple scalar/predicate checks, pass predicates directly
+  g.V().has('age', gt(30))
+  g.V().hasLabel('person')
+  g.V().hasId('v-1')
+
+  // If passing property values into child traversals for complex filtering, 
use filter()
+  g.V().filter(__.values('age').is(gt(30)))
+  ```
+
+---
+
+### 2. `store()` Removed & `aggregate()` Scope Overload Removed
+
+* **Impact**:
+  - The `store('x')` step, previously used for lazy side-effect collection, 
has been completely removed (`No signature of method: store()`).
+  - The `aggregate(Scope, 'x')` overload with an explicit `Scope` (both 
`local` and `global`) has also been removed.
+* **Legacy Query**:
+  ```groovy
+  // Broken: store step removed
+  g.V().store('x').by('age').cap('x')
+
+  // Broken: aggregate(Scope, ...) overload removed
+  g.V().aggregate(local, 'x')
+  g.V().aggregate(global, 'x')
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // 1. Eager global collection (formerly global aggregate): use 
aggregate('x') directly
+  g.V().aggregate('x').by('age').cap('x')
+
+  // 2. Per-object / lazy collection (formerly store or local aggregate): wrap 
in local()
+  g.V().local(__.aggregate('x').by('age')).cap('x')
+  ```
+
+---
+
+### 3. Step `none()` Renamed to `discard()`
+
+* **Impact**:
+  The parameterless `none()` step was originally used to discard all incoming 
traversers (e.g., at the end of `choose()` or `coalesce()` branches). In 3.8.0, 
this step is renamed to **`discard()`**.
+  Meanwhile, 3.8 introduces a new collection predicate step `none(P)` 
(checking if no elements in a collection match predicate P). Calling 
parameterless `none()` in 3.8 triggers argument errors.
+* **Recommended Rewrite**:
+  ```groovy
+  // Legacy:
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.none()) // Error
+
+  // Rewritten: use discard()
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.discard())
+  ```
+
+---
+
+### 4. Strict Behavior for Missing Properties in `by()`
+
+* **Impact**:
+  TinkerPop 3.6+ unified missing value handling across `by()` modulators 
(removing previous default-null behaviors). In 3.8.1, when a property 
referenced by `by()` does not exist:
+  1. **Ordering `order().by('age')`**: Vertices missing `age` are 
**immediately filtered out** (previously they might sort first/last).
+  2. **Projection `project('name', 'age').by('name').by('age')`**: If `age` is 
missing, the returned Map **will not contain the `age` key at all** (previously 
returned `age: null`).
+  3. **Path `path().by('age')`**: If any vertex along the path misses `age`, 
the **entire path is dropped**.
+* **Recommended Rewrite**:
+  If your application requires preserving elements with explicit defaults 
(e.g., `null`), use `coalesce()` inside `by()`:
+  ```groovy
+  // Retain key 'age' with null when missing
+  g.V().project('name', 'age')
+    .by('name')
+    .by(__.coalesce(__.values('age'), __.constant(null)))
+
+  // Provide a typed default for sorting missing fields
+  g.V().order().by(__.coalesce(__.values('age'), __.constant(-1)), desc)
+  ```
+
+---
+
+### 5. `choose()` Semantics Alignment
+
+* **Impact**:
+  - **Single Branch Execution**: When multiple `option()` conditions match 
simultaneously, 3.8 **executes only the first matching branch** (legacy 
versions might execute all matching branches).
+  - **Default Pass-Through**: If the choice child traversal yields no values 
(e.g., property missing) or no `option()` matches, 3.8 **passes the input 
element through unchanged** by default (legacy versions often filtered it out).
+* **Recommended Rewrite**:
+  - To execute multiple matching branches, rewrite using `union()` combined 
with `filter()`.
+  - To filter out elements when no option matches or property is missing, 
explicitly supply `Pick.none` and `Pick.unproductive` branches:
+  ```groovy
+  // Discard unmatched and missing-property inputs
+  g.V().choose(__.values('age'))
+    .option(gt(30), __.values('name'))
+    .option(Pick.none, __.discard())
+    .option(Pick.unproductive, __.discard())
+  ```
+
+---
+
+### 6. Date Types and Time Difference Units
+
+* **Impact**:
+  - **Return Type**: Date steps such as `datetime()` and `dateAdd()` now 
return **`java.time.OffsetDateTime`** instead of `java.util.Date`.
+  - **Unit Change in `dateDiff()`**: The difference between two dates is now 
returned in **milliseconds** instead of seconds (e.g., 1 day difference is 
`86400000` ms instead of `86400` s).
+* **Recommended Rewrite**:
+  - Update Java clients to expect `OffsetDateTime`; convert to 
`java.util.Date` via `Date.from(offsetDateTime.toInstant())` only if strictly 
required.
+  - Review all TTL checks and date comparisons that use `dateDiff()`. Adjust 
multipliers or divide by 1000:
+  ```groovy
+  // Convert dateDiff milliseconds to seconds
+  
g.inject(datetime('2026-10-19T00:00:00Z')).dateDiff(datetime('2026-10-18T00:00:00Z'))
+    .math('_ / 1000').asNumber(GType.LONG)
+  ```
+
+---
+
+## Server Configuration and Client Compatibility
+
+### 1. Serializer Class Names and Package Migration
+In `conf/gremlin-server.yaml`, serializer classes moved from `gremlin-driver` 
to `gremlin-util`. **You must update serializer package names in the 
configuration, as legacy class names will cause ClassNotFoundException**:

Review Comment:
   Important: Changing the package name alone does not give a working 1.8 
serializer config for HugeGraph. The `conf/gremlin-server.yaml` on master sets 
`builder: org.apache.hugegraph.io.HugeGraphTypeSerializerRegistryBuilder` on 
GraphBinary, and adds `org.apache.hugegraph.io.HugeGraphSONV1MessageIoRegistry` 
to untyped GraphSON V1. `docs/server-runtime.md` says to keep both, and 
`GremlinConfigCompatibilityTest` checks that the builder is present. 
`HugeGraphIoRegistry` registers only the Gryo and GraphSON modules, so without 
the builder GraphBinary has no serializer for HugeGraph `Id`, schema, `Blob` or 
enum values. I checked this locally: with gremlin-util 3.8.1, a GraphBinary 
serializer given an unregistered type fails with `IOException: Serializer for 
type ... not found`. The 1.7.0 yaml also has `GraphSONMessageSerializerV2d0`, 
which the table leaves out (its 3.8 name is `GraphSONMessageSerializerV2`). 
Please tell users to start from the `gremlin-server.yaml` that ships with 1.8.0 
 and carry their own edits into it; the quickstart page already says "Use the 
Gremlin configuration files bundled with Server". If the table stays, add the 
builder and registry lines and the V2 row. The CN guide (lines 144-152) needs 
the same change.



##########
content/en/docs/introduction/_index.md:
##########
@@ -43,7 +43,7 @@ HugeGraph Server is the OLTP engine and service entry point 
for the graph databa
 - **Query languages**: Supports Gremlin (TinkerPop 3) and Cypher (OpenCypher)
 - **REST API**: Provides endpoints for schemas, graph data, queries, tasks, 
and operations
 - **Indexes and queries**: Supports exact, range, and compound-condition 
queries
-- **Storage backends**: Versions 1.7.0 through `master` primarily support 
RocksDB (standalone), HStore (distributed), and HBase
+- **Storage backends**: Supports RocksDB (recommended for standalone), HStore 
(recommended for distributed), and HBase (legacy backends such as Cassandra, 
MySQL, and PostgreSQL were deprecated starting in 1.7.0)

Review Comment:
   Minor: "Deprecated starting in 1.7.0" understates what happened. The 1.7.0 
release notes list "BREAKING CHANGE: Disable legacy backends include 
MySQL/PG/c*" (apache/hugegraph#2746). On master, the `hugegraph-cassandra`, 
`hugegraph-mysql`, `hugegraph-postgresql`, `hugegraph-scylladb` and 
`hugegraph-palo` modules are gone. Please say these backends were disabled in 
1.7.0 and have been removed for 1.8.0, so readers of the current docs do not 
expect to be able to select them. CN line 46 needs the same fix.



##########
content/en/docs/guides/gremlin-migration-3.8.md:
##########
@@ -0,0 +1,189 @@
+---
+title: "HugeGraph 1.8.0 Gremlin Migration & Compatibility Guide"
+linkTitle: "1.8 Gremlin & TinkerPop Migration"
+description: "Comprehensive guide to breaking changes, high-frequency syntax 
rewrites, configuration migrations, and complete compatibility references from 
TinkerPop 3.5 to 3.8 in HugeGraph 1.8.0."
+weight: 9
+---
+
+HugeGraph 1.8.0 upgrades its underlying graph traversal and query framework 
from Apache TinkerPop 3.5.1 to **TinkerPop 3.8.1**, requires **Java 17** for 
Server and builds, and updates the script engine to **Groovy 4.0.25**.
+
+While bringing substantial performance optimizations and specification 
alignments, this upgrade introduces several language-level breaking changes. 
This guide highlights the **most critical and frequently used syntax changes** 
with recommended rewrites to ensure seamless migration. Edge cases and 
lower-level protocol details are organized in the [Full Compatibility 
Reference](#full-compatibility-reference) at the end.
+
+> [!NOTE]
+> - This guide applies to upgrades from version 1.7.0 (or earlier) to 1.8.0.
+> - The **Groovy script engine** remains supported in 1.8.0, allowing existing 
multi-line scripts, variable definitions, and Java closures to continue 
functioning as expected.
+
+---
+
+## Top 6 High-Frequency Syntax and Behavioral Changes
+
+Among existing query scripts, the following 6 changes are the most common. 
**Failure to update these may cause query errors or silently return empty 
results.**
+
+### 1. `has(key, traversal)` Overload Removed (High Risk: Silent Empty Results)
+
+* **Impact**:
+  In TinkerPop 3.8.0, the `has(String, Traversal)` and `has(T, Traversal)` 
overloads were removed.
+  In the Groovy script engine, legacy code will not throw a compilation error; 
instead, it **silently falls back to `has(String, Object)`**, comparing the 
anonymous traversal object itself against vertex/edge properties. In practice, 
this **silently yields 0 results / empty sets**!
+* **Legacy Query**:
+  ```groovy
+  // Broken in 3.8: will not throw an error, but silently returns 0 results
+  g.V().has('age', __.is(gt(30)))
+  g.V().has(T.label, __.is('person'))
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // For simple scalar/predicate checks, pass predicates directly
+  g.V().has('age', gt(30))
+  g.V().hasLabel('person')
+  g.V().hasId('v-1')
+
+  // If passing property values into child traversals for complex filtering, 
use filter()
+  g.V().filter(__.values('age').is(gt(30)))
+  ```
+
+---
+
+### 2. `store()` Removed & `aggregate()` Scope Overload Removed
+
+* **Impact**:
+  - The `store('x')` step, previously used for lazy side-effect collection, 
has been completely removed (`No signature of method: store()`).
+  - The `aggregate(Scope, 'x')` overload with an explicit `Scope` (both 
`local` and `global`) has also been removed.
+* **Legacy Query**:
+  ```groovy
+  // Broken: store step removed
+  g.V().store('x').by('age').cap('x')
+
+  // Broken: aggregate(Scope, ...) overload removed
+  g.V().aggregate(local, 'x')
+  g.V().aggregate(global, 'x')
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // 1. Eager global collection (formerly global aggregate): use 
aggregate('x') directly
+  g.V().aggregate('x').by('age').cap('x')
+
+  // 2. Per-object / lazy collection (formerly store or local aggregate): wrap 
in local()
+  g.V().local(__.aggregate('x').by('age')).cap('x')
+  ```
+
+---
+
+### 3. Step `none()` Renamed to `discard()`
+
+* **Impact**:
+  The parameterless `none()` step was originally used to discard all incoming 
traversers (e.g., at the end of `choose()` or `coalesce()` branches). In 3.8.0, 
this step is renamed to **`discard()`**.
+  Meanwhile, 3.8 introduces a new collection predicate step `none(P)` 
(checking if no elements in a collection match predicate P). Calling 
parameterless `none()` in 3.8 triggers argument errors.
+* **Recommended Rewrite**:
+  ```groovy
+  // Legacy:
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.none()) // Error
+
+  // Rewritten: use discard()
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.discard())
+  ```
+
+---
+
+### 4. Strict Behavior for Missing Properties in `by()`
+
+* **Impact**:
+  TinkerPop 3.6+ unified missing value handling across `by()` modulators 
(removing previous default-null behaviors). In 3.8.1, when a property 
referenced by `by()` does not exist:
+  1. **Ordering `order().by('age')`**: Vertices missing `age` are 
**immediately filtered out** (previously they might sort first/last).
+  2. **Projection `project('name', 'age').by('name').by('age')`**: If `age` is 
missing, the returned Map **will not contain the `age` key at all** (previously 
returned `age: null`).
+  3. **Path `path().by('age')`**: If any vertex along the path misses `age`, 
the **entire path is dropped**.
+* **Recommended Rewrite**:
+  If your application requires preserving elements with explicit defaults 
(e.g., `null`), use `coalesce()` inside `by()`:
+  ```groovy
+  // Retain key 'age' with null when missing
+  g.V().project('name', 'age')
+    .by('name')
+    .by(__.coalesce(__.values('age'), __.constant(null)))
+
+  // Provide a typed default for sorting missing fields
+  g.V().order().by(__.coalesce(__.values('age'), __.constant(-1)), desc)
+  ```
+
+---
+
+### 5. `choose()` Semantics Alignment
+
+* **Impact**:
+  - **Single Branch Execution**: When multiple `option()` conditions match 
simultaneously, 3.8 **executes only the first matching branch** (legacy 
versions might execute all matching branches).
+  - **Default Pass-Through**: If the choice child traversal yields no values 
(e.g., property missing) or no `option()` matches, 3.8 **passes the input 
element through unchanged** by default (legacy versions often filtered it out).
+* **Recommended Rewrite**:
+  - To execute multiple matching branches, rewrite using `union()` combined 
with `filter()`.
+  - To filter out elements when no option matches or property is missing, 
explicitly supply `Pick.none` and `Pick.unproductive` branches:
+  ```groovy
+  // Discard unmatched and missing-property inputs
+  g.V().choose(__.values('age'))
+    .option(gt(30), __.values('name'))
+    .option(Pick.none, __.discard())
+    .option(Pick.unproductive, __.discard())
+  ```
+
+---
+
+### 6. Date Types and Time Difference Units
+
+* **Impact**:
+  - **Return Type**: Date steps such as `datetime()` and `dateAdd()` now 
return **`java.time.OffsetDateTime`** instead of `java.util.Date`.
+  - **Unit Change in `dateDiff()`**: The difference between two dates is now 
returned in **milliseconds** instead of seconds (e.g., 1 day difference is 
`86400000` ms instead of `86400` s).
+* **Recommended Rewrite**:
+  - Update Java clients to expect `OffsetDateTime`; convert to 
`java.util.Date` via `Date.from(offsetDateTime.toInstant())` only if strictly 
required.
+  - Review all TTL checks and date comparisons that use `dateDiff()`. Adjust 
multipliers or divide by 1000:
+  ```groovy
+  // Convert dateDiff milliseconds to seconds
+  
g.inject(datetime('2026-10-19T00:00:00Z')).dateDiff(datetime('2026-10-18T00:00:00Z'))
+    .math('_ / 1000').asNumber(GType.LONG)
+  ```
+
+---
+
+## Server Configuration and Client Compatibility
+
+### 1. Serializer Class Names and Package Migration
+In `conf/gremlin-server.yaml`, serializer classes moved from `gremlin-driver` 
to `gremlin-util`. **You must update serializer package names in the 
configuration, as legacy class names will cause ClassNotFoundException**:
+
+| Legacy Class (`driver.ser.*`) | 1.8.0 Class (`util.ser.*`) | Notes |
+|---|---|---|
+| `GraphBinaryMessageSerializerV1` | 
`org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1` | 
Recommended default binary serializer |
+| `GraphSONMessageSerializerV1d0` | 
`org.apache.tinkerpop.gremlin.util.ser.GraphSONUntypedMessageSerializerV1` | 
Retains untyped JSON (do not just remove `d0`, which becomes typed) |
+| `GraphSONMessageSerializerV3d0` | 
`org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3` | Standard 
Typed GraphSON V3 |
+{.td-table--wide}
+
+### 2. Can HugeGraph Client 1.5.0 Continue to Work?
+* **Verdict**: **Yes**.
+* HugeGraph Server 1.8.0 provides backward-compatible adapters (graph alias 
mapping and legacy auth path redirection). Applications using 
`hugegraph-client:1.5.0` can continue standard CRUD, schema management, and 
REST operations without forced SDK upgrades.
+* **Important Note**: Although Client 1.5.0 connects successfully, **all 
submitted Gremlin script strings are executed on the 3.8.1 server engine**. 
Therefore, Gremlin queries constructed in your code must comply with the 3.8 
rules described above.
+
+---
+
+## Full Compatibility Reference
+
+### Appendix 1: Writes & Upsert (`mergeV` / `mergeE`)
+- **M01**: `onCreate` property maps strictly inherit the search match map. 
Conflicting keys cannot overwrite matched properties.
+- **M02**: `mergeE` no longer implicitly binds incoming/outgoing vertices from 
upstream traversers; specify `Direction.OUT` and `Direction.IN` in the map or 
use explicit options.
+- **M03**: Conflicting `onCreate` / `onMatch` maps are validated during 
construction rather than deferred to runtime execution.
+- **M04**: In 3.8, child traversers in `onMatch` receive the matched Element 
object rather than the original input Map. Preserve input map references prior 
to merge with `.as('input')` and reference with `select('input')`.
+
+### Appendix 2: Advanced Traversal Steps & Collections
+- **B07 (`local()` unpacks bulk)**: Traversers with bulk counters are expanded 
into individual items when entering `local()` child traversals. Use 
`groupCount()` for frequency analysis.
+- **B09 (`range(local)` collection unpacking)**: Slicing a single item from a 
list (e.g., `limit(local, 1)`) consistently returns a Collection wrapper 
(`[item]`). Append `.unfold()` if a scalar is needed.
+- **B11 (`sum()` return type)**: Summing integer streams without overflow may 
return `Integer` instead of `Long`. Clients should accept `Number`.
+- **B14 (`split('')`)**: Splitting with an empty separator returns a list of 
individual characters.
+- **B15 (`asString()` on null)**: `asString()` throws an 
`IllegalArgumentException` on null inputs.
+
+### Appendix 3: GLV Client Variations
+- **Python**: Avoids Python keyword conflicts by appending an underscore to 
step names (`filter_()`, `id_()`, `range_()`, `max_()`).
+- **JavaScript**: Set collections are returned as native ECMAScript `Set` 
instances (use `.size` and `.has()`). Deprecated `connectOnStartup` option 
removed; call `await connection.open()`.
+- **.NET**: `byte` values serialize strictly as signed bytes (`sbyte`).
+- **Go**: BigDecimal/BigInt aligned; always inspect errors on `Next()`.
+
+### Appendix 4: Network Protocols & Serializer Guardrails
+- **C03 (OLTP element properties)**: Remote OLTP queries return elements with 
full properties by default rather than reference tokens only. Use `project()` 
or `valueMap()` to restrict payload sizes when necessary.
+- **C06 (GraphSON payload limits)**: Added guardrails for max number length 
(10,000), max string length (20,000,000), and max nesting depth (1,000).
+
+### Appendix 5: HugeGraph Feature Capabilities
+- **Meta-Properties Unsupported**: HugeGraph strictly follows its native 
schema design and does not support TinkerPop meta-properties (properties on 
properties). Writing property metadata in 1.8.0 will be **explicitly rejected**.

Review Comment:
   Minor: 1.8.0 does not change this. At the 1.7.0 tag, 
`HugeVertex.property(cardinality, key, value, objects...)` already throws 
`VertexProperty.Exceptions.metaPropertiesNotSupported()` when key-values are 
passed, and `HugeVertexProperty.property(key, value)` throws 
`NotSupportException("nested property")`. Master has the same code. CN line 190 
also says the write is "no longer implicitly degraded" (不再隐式退化), which 
describes a 1.7 behaviour that never existed. Please describe it as unchanged 
behaviour.



##########
content/en/docs/guides/gremlin-migration-3.8.md:
##########
@@ -0,0 +1,189 @@
+---
+title: "HugeGraph 1.8.0 Gremlin Migration & Compatibility Guide"
+linkTitle: "1.8 Gremlin & TinkerPop Migration"
+description: "Comprehensive guide to breaking changes, high-frequency syntax 
rewrites, configuration migrations, and complete compatibility references from 
TinkerPop 3.5 to 3.8 in HugeGraph 1.8.0."
+weight: 9
+---
+
+HugeGraph 1.8.0 upgrades its underlying graph traversal and query framework 
from Apache TinkerPop 3.5.1 to **TinkerPop 3.8.1**, requires **Java 17** for 
Server and builds, and updates the script engine to **Groovy 4.0.25**.
+
+While bringing substantial performance optimizations and specification 
alignments, this upgrade introduces several language-level breaking changes. 
This guide highlights the **most critical and frequently used syntax changes** 
with recommended rewrites to ensure seamless migration. Edge cases and 
lower-level protocol details are organized in the [Full Compatibility 
Reference](#full-compatibility-reference) at the end.
+
+> [!NOTE]
+> - This guide applies to upgrades from version 1.7.0 (or earlier) to 1.8.0.
+> - The **Groovy script engine** remains supported in 1.8.0, allowing existing 
multi-line scripts, variable definitions, and Java closures to continue 
functioning as expected.
+
+---
+
+## Top 6 High-Frequency Syntax and Behavioral Changes
+
+Among existing query scripts, the following 6 changes are the most common. 
**Failure to update these may cause query errors or silently return empty 
results.**
+
+### 1. `has(key, traversal)` Overload Removed (High Risk: Silent Empty Results)
+
+* **Impact**:
+  In TinkerPop 3.8.0, the `has(String, Traversal)` and `has(T, Traversal)` 
overloads were removed.
+  In the Groovy script engine, legacy code will not throw a compilation error; 
instead, it **silently falls back to `has(String, Object)`**, comparing the 
anonymous traversal object itself against vertex/edge properties. In practice, 
this **silently yields 0 results / empty sets**!
+* **Legacy Query**:
+  ```groovy
+  // Broken in 3.8: will not throw an error, but silently returns 0 results
+  g.V().has('age', __.is(gt(30)))
+  g.V().has(T.label, __.is('person'))
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // For simple scalar/predicate checks, pass predicates directly
+  g.V().has('age', gt(30))
+  g.V().hasLabel('person')
+  g.V().hasId('v-1')
+
+  // If passing property values into child traversals for complex filtering, 
use filter()
+  g.V().filter(__.values('age').is(gt(30)))
+  ```
+
+---
+
+### 2. `store()` Removed & `aggregate()` Scope Overload Removed
+
+* **Impact**:
+  - The `store('x')` step, previously used for lazy side-effect collection, 
has been completely removed (`No signature of method: store()`).
+  - The `aggregate(Scope, 'x')` overload with an explicit `Scope` (both 
`local` and `global`) has also been removed.
+* **Legacy Query**:
+  ```groovy
+  // Broken: store step removed
+  g.V().store('x').by('age').cap('x')
+
+  // Broken: aggregate(Scope, ...) overload removed
+  g.V().aggregate(local, 'x')
+  g.V().aggregate(global, 'x')
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // 1. Eager global collection (formerly global aggregate): use 
aggregate('x') directly
+  g.V().aggregate('x').by('age').cap('x')
+
+  // 2. Per-object / lazy collection (formerly store or local aggregate): wrap 
in local()
+  g.V().local(__.aggregate('x').by('age')).cap('x')
+  ```
+
+---
+
+### 3. Step `none()` Renamed to `discard()`
+
+* **Impact**:
+  The parameterless `none()` step was originally used to discard all incoming 
traversers (e.g., at the end of `choose()` or `coalesce()` branches). In 3.8.0, 
this step is renamed to **`discard()`**.
+  Meanwhile, 3.8 introduces a new collection predicate step `none(P)` 
(checking if no elements in a collection match predicate P). Calling 
parameterless `none()` in 3.8 triggers argument errors.
+* **Recommended Rewrite**:
+  ```groovy
+  // Legacy:
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.none()) // Error

Review Comment:
   Minor: This "Legacy" line fails on 1.7.0 too. TinkerPop 3.5.1 has no 
anonymous `__.none()`, so the 3.5.1 Groovy engine fails with 
`MissingMethodException: No signature of method: static ...__.none()`. Only the 
traversal method existed: `g.V().none()` returns `[]` on 3.5.1, and on 3.8.1 it 
fails with `IllegalArgumentException: Input predicate to none step can't be 
null.` Please use a legacy example that ran on 3.5.1, such as 
`g.V().hasLabel('person').none()` rewritten to `.discard()`, and quote the 
3.8.1 error so users can search for it. CN line 79 needs the same fix.



##########
content/en/docs/changelog/hugegraph-1.8.0-release-notes.md:
##########
@@ -0,0 +1,42 @@
+---
+title: "HugeGraph 1.8.0 Release Notes"
+linkTitle: "Release-1.8.0"
+weight: 1
+---
+
+> WIP: This doc is under construction, please wait for the final version (BETA)
+
+### Runtime & Version Requirements
+
+- **Java Environment**: **1.8.0** HugeGraph components (Server, PD, Store) 
require **Java 17** for runtime and source builds (1.7.0 is the last release 
supporting Java 11).
+- **Query & Script Engine**: Graph traversal framework upgraded to **Apache 
TinkerPop 3.8.1**, script engine upgraded to **Groovy 4.0.25**.
+
+### Key Breaking Changes & Compatibility
+
+#### 1. Critical Gremlin Traversal Breaking Changes
+- **Removed `has(key, traversal)` overload**: In Groovy, legacy syntax 
silently falls back to Object comparison, resulting in **0 results / empty 
sets** without throwing an error. Use `has('age', gt(30))` for simple 
conditions, or `filter(__.values('age').is(gt(30)))` for child traversals.
+- **Removed `store()` & scoped `aggregate()`**: Use `aggregate('x')` for 
global eager collection; use `local(__.aggregate('x'))` for lazy or per-object 
collection.
+- **Step `none()` renamed to `discard()`**: Discarding incoming traversers 
must now use `discard()` (avoids collision with new collection predicate 
`none(P)`).
+- **Strict `by()` behavior on missing properties**: Vertices missing 
properties are dropped in `order().by()`; keys are omitted from maps in 
`project().by()`; paths are discarded in `path().by()`. Wrap with `coalesce()` 
to provide explicit defaults if preservation is needed.
+- **`choose()` semantics alignment**: Executes only the first matching branch 
when conditions overlap; passes elements through unchanged by default when no 
branch matches or values are absent.
+- **Date types & unit changes**: Date operations return `OffsetDateTime` 
instead of `java.util.Date`; `dateDiff()` results are in **milliseconds instead 
of seconds**.
+
+> For comprehensive query comparison examples and the full migration 
checklist, see the [HugeGraph 1.8.0 Gremlin Migration & Compatibility 
Guide](../guides/gremlin-migration-3.8).
+
+#### 2. Server Configuration & Client Compatibility
+- **Serializer class names**: Serializer packages in 
`conf/gremlin-server.yaml` moved from 
`org.apache.tinkerpop.gremlin.driver.ser.*` to 
`org.apache.tinkerpop.gremlin.util.ser.*`.
+- **HugeGraph Client 1.5.0**: Supported via server-side backward-compatibility 
adapters; however, Gremlin query strings must follow TinkerPop 3.8 syntax.
+- **GPL word analyzer removed**: Use IK, SmartCN, or other compliant analyzers.

Review Comment:
   Important: The word analyzer is still in 1.8. 
`hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/WordAnalyzer.java`
 is on master; apache/hugegraph#3295 only stopped bundling the GPLv3 
`org.apdplat:word:1.3` jar. According to `docs/BUILDING.md` on master, a graph 
configured with `search.text_analyzer=word` keeps working once `word-1.3.jar` 
is placed in the Server's `lib/` directory. Without the jar, the graph fails 
with a configuration error that names the missing dependency. If users follow 
this note and switch to IK or SmartCN, text gets segmented differently, and 
existing search-index entries written with `word` may stop matching new queries 
unless the index is rebuilt. Please say that the jar is no longer bundled and 
that graphs using `word` need `word-1.3.jar` added to `lib/`. CN line 29 needs 
the same fix.



##########
content/en/docs/guides/gremlin-migration-3.8.md:
##########
@@ -0,0 +1,189 @@
+---
+title: "HugeGraph 1.8.0 Gremlin Migration & Compatibility Guide"
+linkTitle: "1.8 Gremlin & TinkerPop Migration"
+description: "Comprehensive guide to breaking changes, high-frequency syntax 
rewrites, configuration migrations, and complete compatibility references from 
TinkerPop 3.5 to 3.8 in HugeGraph 1.8.0."
+weight: 9
+---
+
+HugeGraph 1.8.0 upgrades its underlying graph traversal and query framework 
from Apache TinkerPop 3.5.1 to **TinkerPop 3.8.1**, requires **Java 17** for 
Server and builds, and updates the script engine to **Groovy 4.0.25**.
+
+While bringing substantial performance optimizations and specification 
alignments, this upgrade introduces several language-level breaking changes. 
This guide highlights the **most critical and frequently used syntax changes** 
with recommended rewrites to ensure seamless migration. Edge cases and 
lower-level protocol details are organized in the [Full Compatibility 
Reference](#full-compatibility-reference) at the end.
+
+> [!NOTE]
+> - This guide applies to upgrades from version 1.7.0 (or earlier) to 1.8.0.
+> - The **Groovy script engine** remains supported in 1.8.0, allowing existing 
multi-line scripts, variable definitions, and Java closures to continue 
functioning as expected.
+
+---
+
+## Top 6 High-Frequency Syntax and Behavioral Changes
+
+Among existing query scripts, the following 6 changes are the most common. 
**Failure to update these may cause query errors or silently return empty 
results.**
+
+### 1. `has(key, traversal)` Overload Removed (High Risk: Silent Empty Results)
+
+* **Impact**:
+  In TinkerPop 3.8.0, the `has(String, Traversal)` and `has(T, Traversal)` 
overloads were removed.
+  In the Groovy script engine, legacy code will not throw a compilation error; 
instead, it **silently falls back to `has(String, Object)`**, comparing the 
anonymous traversal object itself against vertex/edge properties. In practice, 
this **silently yields 0 results / empty sets**!
+* **Legacy Query**:
+  ```groovy
+  // Broken in 3.8: will not throw an error, but silently returns 0 results
+  g.V().has('age', __.is(gt(30)))
+  g.V().has(T.label, __.is('person'))
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // For simple scalar/predicate checks, pass predicates directly
+  g.V().has('age', gt(30))
+  g.V().hasLabel('person')
+  g.V().hasId('v-1')
+
+  // If passing property values into child traversals for complex filtering, 
use filter()
+  g.V().filter(__.values('age').is(gt(30)))
+  ```
+
+---
+
+### 2. `store()` Removed & `aggregate()` Scope Overload Removed
+
+* **Impact**:
+  - The `store('x')` step, previously used for lazy side-effect collection, 
has been completely removed (`No signature of method: store()`).
+  - The `aggregate(Scope, 'x')` overload with an explicit `Scope` (both 
`local` and `global`) has also been removed.
+* **Legacy Query**:
+  ```groovy
+  // Broken: store step removed
+  g.V().store('x').by('age').cap('x')
+
+  // Broken: aggregate(Scope, ...) overload removed
+  g.V().aggregate(local, 'x')
+  g.V().aggregate(global, 'x')
+  ```
+* **Recommended Rewrite**:
+  ```groovy
+  // 1. Eager global collection (formerly global aggregate): use 
aggregate('x') directly
+  g.V().aggregate('x').by('age').cap('x')
+
+  // 2. Per-object / lazy collection (formerly store or local aggregate): wrap 
in local()
+  g.V().local(__.aggregate('x').by('age')).cap('x')
+  ```
+
+---
+
+### 3. Step `none()` Renamed to `discard()`
+
+* **Impact**:
+  The parameterless `none()` step was originally used to discard all incoming 
traversers (e.g., at the end of `choose()` or `coalesce()` branches). In 3.8.0, 
this step is renamed to **`discard()`**.
+  Meanwhile, 3.8 introduces a new collection predicate step `none(P)` 
(checking if no elements in a collection match predicate P). Calling 
parameterless `none()` in 3.8 triggers argument errors.
+* **Recommended Rewrite**:
+  ```groovy
+  // Legacy:
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.none()) // Error
+
+  // Rewritten: use discard()
+  g.V().choose(__.values('age')).option(gt(30), 
__.values('name')).option(Pick.none, __.discard())
+  ```
+
+---
+
+### 4. Strict Behavior for Missing Properties in `by()`
+
+* **Impact**:
+  TinkerPop 3.6+ unified missing value handling across `by()` modulators 
(removing previous default-null behaviors). In 3.8.1, when a property 
referenced by `by()` does not exist:
+  1. **Ordering `order().by('age')`**: Vertices missing `age` are 
**immediately filtered out** (previously they might sort first/last).
+  2. **Projection `project('name', 'age').by('name').by('age')`**: If `age` is 
missing, the returned Map **will not contain the `age` key at all** (previously 
returned `age: null`).
+  3. **Path `path().by('age')`**: If any vertex along the path misses `age`, 
the **entire path is dropped**.
+* **Recommended Rewrite**:
+  If your application requires preserving elements with explicit defaults 
(e.g., `null`), use `coalesce()` inside `by()`:
+  ```groovy
+  // Retain key 'age' with null when missing
+  g.V().project('name', 'age')
+    .by('name')
+    .by(__.coalesce(__.values('age'), __.constant(null)))
+
+  // Provide a typed default for sorting missing fields
+  g.V().order().by(__.coalesce(__.values('age'), __.constant(-1)), desc)
+  ```
+
+---
+
+### 5. `choose()` Semantics Alignment
+
+* **Impact**:
+  - **Single Branch Execution**: When multiple `option()` conditions match 
simultaneously, 3.8 **executes only the first matching branch** (legacy 
versions might execute all matching branches).
+  - **Default Pass-Through**: If the choice child traversal yields no values 
(e.g., property missing) or no `option()` matches, 3.8 **passes the input 
element through unchanged** by default (legacy versions often filtered it out).

Review Comment:
   Minor: On 1.7.0 (TinkerPop 3.5.1), an element whose choice traversal returns 
nothing is not filtered out; the query throws. On the modern graph, 
`g.V().choose(__.values('age')).option(gt(30), __.values('name'))` fails on 
3.5.1 with `IllegalArgumentException: The provided traverser does not map to a 
value: v[3]->[PropertiesStep([age],value)]`. On 3.8.1 it passes `lop` and 
`ripple` through. The no-match case is as described: 3.5.1 drops `vadas`, and 
3.8.1 passes `v[2]` through. Please say that a missing property used to raise 
this error and now passes the element through, so users can find these queries 
by the old error text. CN line 112 needs the same fix.



##########
content/en/docs/language/hugegraph-gremlin.md:
##########
@@ -96,7 +100,9 @@ HugeGraph supports all steps of Gremlin. For complete 
reference information abou
 | coalesce   | Returns the first traversal that returns a result.              
                                                                      | 
[coalesce 
step](http://tinkerpop.apache.org/docs/current/reference/#coalesce-step)     |
 | constant   | Returns a constant value. Used in conjunction with coalesce.    
                                                                      | 
[constant 
step](http://tinkerpop.apache.org/docs/current/reference/#constant-step)     |
 | count      | Returns a count from the traversal.                             
                                                            | [count 
step](http://tinkerpop.apache.org/docs/current/reference/#count-step)         |
+| datetime   | Creates a datetime object or retrieves current server time 
(returns `OffsetDateTime` in 1.8.0).     | [datetime 
step](http://tinkerpop.apache.org/docs/current/reference/#datetime-step)     |

Review Comment:
   Minor: The TinkerPop reference has no `#datetime-step` anchor. The current 
(3.8.2) page has `discard-step`, `mergevertex-step` and `mergeedge-step`, and 
for dates it has `asDate-step`, `dateAdd-step` and `dateDiff-step`. 
`datetime()` is a Gremlin language function, documented under 
`gremlin-groovy-differences`, so this link opens at the top of a very long 
page. Please link to `#gremlin-groovy-differences` or to one of the date-step 
anchors. CN line 103 needs the same fix.



-- 
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