

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon Neptune 中的 openCypher 规范合规性
<a name="feature-opencypher-compliance"></a>

Amazon Neptune 版本的 openCypher 通常支持当前 openCypher 规范（即 [Cypher 查询语言参考版本 9](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf)）中定义的子句、运算符、表达式、函数和语法。下面列出了 Neptune 对 openCypher 的支持的局限性和差异。

 Amazon Neptune 还支持 openCypher 规范范围之外的多项功能。有关详细信息，请参阅[Amazon Neptune 中的 openCypher 扩展](access-graph-opencypher-extensions.md)。

**注意**  
Cypher 的当前 Neo4j 实现包含上述 openCypher 规范中未包含的功能。如果您要将当前 Cypher 代码迁移到 Neptune，请参阅[Neptune 与 Neo4j 的兼容性](migration-compatibility.md)和[重写 Cypher 查询以在 Neptune 上的 openCypher 中运行](migration-opencypher-rewrites.md)以了解更多信息。

## Neptune 中对 openCypher 子句的支持
<a name="opencypher-compliance-clauses"></a>

除非另有说明，否则 Neptune 支持以下子句：
+ `MATCH` – 支持，但除了目前不支持 *`shortestPath()`* 和 *`allShortestPaths()`* 之外。
+ `OPTIONAL MATCH`
+ *`MANDATORY MATCH`* –Neptune 目前**不**支持。但是，Neptune 确实支持在 `MATCH` 查询中使用[自定义 ID 值](access-graph-opencypher-extensions.md#opencypher-compliance-custom-ids)。
+ `RETURN` – 支持，但与 `SKIP` 或 `LIMIT` 的非静态值结合使用时除外。例如，以下内容目前不起作用：

  ```
  MATCH (n)
  RETURN n LIMIT toInteger(rand())    // Does NOT work!
  ```
+ `WITH` – 支持，但与 `SKIP` 或 `LIMIT` 的非静态值结合使用时除外。例如，以下内容目前不起作用：

  ```
  MATCH (n)
  WITH n SKIP toInteger(rand())
  WITH count() AS count
  RETURN count > 0 AS nonEmpty    // Does NOT work!
  ```
+ `UNWIND`
+ `WHERE`
+ `ORDER BY`
+ `SKIP`
+ `LIMIT`
+ `CREATE` – Neptune 允许您在 `CREATE` 查询中创建[自定义 ID 值](access-graph-opencypher-extensions.md#opencypher-compliance-custom-ids)。
+ `DELETE`
+ `SET`
+ `REMOVE`
+ `MERGE` – Neptune 支持在 `MERGE` 查询中使用[自定义 ID 值](access-graph-opencypher-extensions.md#opencypher-compliance-custom-ids)。
+ *`CALL[YIELD...]`* –Neptune 目前**不**支持。
+ `UNION, UNION ALL` – 支持只读查询，但目前**不**支持突变查询。
+  `USING` – 从引擎版本 [1.3.2.0](https://docs.aws.amazon.com//neptune/latest/userguide/engine-releases-1.3.2.0.html) 开始支持 `USING`。有关更多信息，请参阅[查询提示](https://docs.aws.amazon.com//neptune/latest/userguide/opencypher-query-hints.html)。

## Neptune 中对 openCypher 运算符的支持
<a name="opencypher-compliance-operators"></a>

除非另有说明，否则 Neptune 支持以下运算符：

**一般运算符**
+ `DISTINCT`
+ 用于访问嵌套文本映射的属性的 `.` 运算符。

**数学运算**
+ `+` 加法运算符。
+ `-` 减法运算符。
+ `*` 乘法运算符。
+ `/` 除法运算符。
+ `%` 模除运算符。
+ 取`^`指数运算符。*is NOT supported*

**比较运算符**
+ `=` 加法运算符。
+ `<>` 不等于运算符。
+ 支持 `<` 小于运算符，除非其中一个参数是路径、列表或映射。
+ 支持 `>` 大于运算符，除非其中一个参数是路径、列表或映射。
+ 支持 `<=` less-than-or-equal-to 运算符，除非其中一个参数是路径、列表或地图。
+ 支持 `>=` greater-than-or-equal-to 运算符，除非其中一个参数是路径、列表或地图。
+ `IS NULL`
+ `IS NOT NULL`
+ 如果要搜索的数据是字符串，则支持 `STARTS WITH`。
+ 如果要搜索的数据是字符串，则支持 `ENDS WITH`。
+ 如果要搜索的数据是字符串，则支持 `CONTAINS`。

**布尔运算符**
+ `AND`
+ `OR`
+ `XOR`
+ `NOT`

**字符串运算符**
+ `+` 联接运算符。

**列表运算符**
+ `+` 联接运算符。
+ `IN`（检查列表中是否存在某个项目）

## Neptune 中对 openCypher 表达式的支持
<a name="opencypher-compliance-expressions"></a>

除非另有说明，否则 Neptune 支持以下表达式：
+ `CASE`
+ Neptune 目前**不**支持使用 `[]` 表达式来访问节点、关系或映射中动态计算的属性键。例如，以下内容不起作用：

  ```
  MATCH (n)
  WITH [5, n, {key: 'value'}] AS list
  RETURN list[1].name
  ```

## Neptune 中对 openCypher 函数的支持
<a name="opencypher-compliance-functions"></a>

除非另有说明，否则 Neptune 支持以下函数：

**谓词函数**
+ `exists()`

**标量函数**
+ `coalesce()`
+ `endNode()`
+ `epochmillis()`
+ `head()`
+ `id()`
+ `last()`
+ `length()`
+ `randomUUID()`
+ `properties()`
+ `removeKeyFromMap`
+ `size()` – 此重载方法目前仅适用于模式表达式、列表和字符串
+ `startNode()`
+ `timestamp()`
+ `toBoolean()`
+ `toFloat()`
+ `toInteger()`
+ `type()`

**聚合函数**
+ `avg()`
+ `collect()`
+ `count()`
+ `max()`
+ `min()`
+ `percentileDisc()`
+ `stDev()`
+ `percentileCont()`
+ `stDevP()`
+ `sum()`

**列出函数**
+ [`join()`](access-graph-opencypher-extensions.md#opencypher-compliance-join-function)（将列表中的字符串联接成单个字符串）
+ `keys()`
+ `labels()`
+ `nodes()`
+ `range()`
+ `relationships()`
+ `reverse()`
+ `tail()`

**数学函数 - 数字**
+ `abs()`
+ `ceil()`
+ `floor()`
+ `rand()`
+ `round()`
+ `sign()`

**数学函数 - 对数**
+ `e()`
+ `exp()`
+ `log()`
+ `log10()`
+ `sqrt()`

**数学函数 - 三角函数**
+ `acos()`
+ `asin()`
+ `atan()`
+ `atan2()`
+ `cos()`
+ `cot()`
+ `degrees()`
+ `pi()`
+ `radians()`
+ `sin()`
+ `tan()`

**字符串函数**
+ [`join()`](access-graph-opencypher-extensions.md#opencypher-compliance-join-function)（将列表中的字符串联接成单个字符串）
+ `left()`
+ `lTrim()`
+ `replace()`
+ `reverse()`
+ `right()`
+ `rTrim()`
+ `split()`
+ `substring()`
+ `toLower()`
+ `toString()`
+ `toUpper()`
+ `trim()`

**用户定义的函数**

*User-defined functions*Neptune 目前**不**支持。

## Neptune 特定的 openCypher 实现细节
<a name="opencypher-compliance-differences"></a>

以下各节描述了 openCypher 的 Neptune 实现可能与 [openCypher 规范](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf)不同或超出该规范的方式。

### Neptune 中的可变长度路径 (VLP) 求值
<a name="opencypher-compliance-differences-vlp"></a>

可变长度路径 (`VLP`) 求值会发现图形中节点之间的路径。查询中的路径长度可以不受限制。为了防止循环，[openCypher 规范](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf)规定，每个解最多只能遍历每个边缘一次。

因为 VLPs，Neptune 实现与 OpenCypher 规范的不同之处在于，它仅支持属性相等过滤器的常量值。执行以下查询：

```
MATCH (x)-[:route*1..2 {dist:33, code:x.name}]->(y) return x,y
```

由于 `x.name` 属性相等筛选条件值不是常量，因此，此查询会导致 `UnsupportedOperationException`，并显示消息：`Property predicate over variable-length relationships with non-constant expression is not supported in this release.`

### Neptune openCypher 实施中的时间支持（Neptune 数据库 1.3.1.0 及更低版本）
<a name="opencypher-compliance-time"></a>

Neptune 目前为 openCypher 中的时间函数提供有限支持。它支持对时间类型使用 `DateTime` 数据类型。

`datetime()` 函数可用于获取当前的 UTC 日期和时间，如下所示：

```
RETURN  datetime() as res
```

日期和时间值可以从 `"`*date*`T`*time*`"` 格式的字符串中解析，其中 *date* 和 *time* 都以下面支持的形式表示：

**支持的日期格式**
+ `yyyy-MM-dd`
+ `yyyyMMdd`
+ `yyyy-MM`
+ `yyyy-DDD`
+ `yyyyDDD`
+ `yyyy`

**支持的时间格式**
+ `HH:mm:ssZ`
+ `HHmmssZ`
+ `HH:mm:ssZ`
+ `HH:mmZ`
+ `HHmmZ`
+ `HHZ`
+ `HHmmss`
+ `HH:mm:ss`
+ `HH:mm`
+ `HHmm`
+ `HH`

例如：

```
RETURN datetime('2022-01-01T00:01')      // or another example:
RETURN datetime('2022T0001')
```

请注意，Neptune OpenCypher 中的所有 date/time 值均作为 UTC 值存储和检索。

Neptune openCypher 使用 `statement` 时钟，这意味着在查询的整个持续时间内使用相同的时刻。同一事务中的不同查询可能会使用不同的时刻。

Neptune 不支持在对 `datetime()` 的调用中使用函数。例如，以下内容不起作用：

```
CREATE (:n {date:datetime(tostring(2021))})  // ---> NOT ALLOWED!
```

Neptune 确实支持将 `datetime` 转换为 `epochmillis` 的 `epochmillis()` 函数。例如：

```
MATCH (n) RETURN epochMillis(n.someDateTime)
1698972364782
```

Neptune 目前对 `DateTime` 对象不支持其它函数和操作，例如加法和减法。

### Neptune openCypher 实施中的时间支持（Neptune Analytics 和 Neptune 数据库 1.3.2.0 及更高版本）
<a name="opencypher-compliance-time-na"></a>

以下日期时间功能 OpenCypher 适用于 Neptune Analytics。或者，您可以使用实验室模式参数 `DatetimeMillisecond=enabled` 在 Neptune 引擎发行版本 1.3.2.0 及更高版本上启用以下日期时间功能。有关在实验室模式下使用此功能的更多详细信息，请参阅[扩展日期时间支持](features-lab-mode.md#labmode-extended-datetime-support)。
+ 支持毫秒。即使毫秒为 0，日期时间文本也将始终以毫秒为单位返回。（之前的行为是截断毫秒。）

  ```
  CREATE (:event {time: datetime('2024-04-01T23:59:59Z')})
  
  # Returning the date returns with 000 suffixed representing milliseconds
  MATCH(n:event)
  RETURN n.time as datetime
  
  {
    "results" : [ {
      "n" : {
        "~id" : "0fe88f7f-a9d9-470a-bbf2-fd6dd5bf1a7d",
        "~entityType" : "node",
        "~labels" : [ "event" ],
        "~properties" : {
          "time" : "2024-04-01T23:59:59.000Z"
        }
      }
    } ]
  }
  ```
+ 支持通过存储的属性或中间结果调用 datetime() 函数。例如，在此功能推出之前，无法执行以下查询。

  通过属性调用 Datetime()：

  ```
  // Create node with property 'time' stored as string
  CREATE (:event {time: '2024-04-01T23:59:59Z'})
  
  // Match and return this property as datetime
  MATCH(n:event)
  RETURN datetime(n.time) as datetime
  ```

  通过中间结果调用 Datetime()：

  ```
  // Parse datetime from parameter
  UNWIND $list as myDate
  RETURN datetime(myDate) as d
  ```
+ 现在也可以保存上述情况下创建的日期时间属性。

  将日期时间从一个属性的字符串属性保存到另一个属性：

  ```
  // Create node with property 'time' stored as string
  CREATE (:event {time: '2024-04-01T23:59:59Z', name: 'crash'})
  
  // Match and update the same property to datetime type
  MATCH(n:event {name: 'crash'})
  SET n.time = datetime(n.time)
  
  // Match and update another node's property
  MATCH(e:event {name: 'crash'})
  MATCH(n:server {name: e.servername})
  SET n.time = datetime(e.time)
  ```

  使用带有日期时间属性的参数批量创建节点：

  ```
  // Batch create from parameter
  UNWIND $list as events
  CREATE (n:crash) {time: datetime(events.time)}
  // Parameter value
  {
    "x":[
      {"time":"2024-01-01T23:59:29", "name":"crash1"},
      {"time":"2023-01-01T00:00:00Z", "name":"crash2"}
    ]
  }
  ```
+ Support 支持更大的 ISO8601 日期时间格式子集。请参阅下面的。

支持的格式

 日期时间值的格式为 [Date]T[Time][Timezone]，其中 T 是分隔符。如果未提供明确的时区，则假定 UTC (Z) 为默认时区。

Timezone

支持的时区格式包括：
+ \$1/-HH:mm
+ \$1/-HHmm
+ \$1/-HH

 日期时间字符串中的时区是可选的。如果时区偏移量为 0，则可以使用 Z 代替上述的时区后缀来指示 UTC 时间。支持的时区范围为 -14:00 到 \$114:00。

日期

如果不存在时区，或者时区为 UTC (Z)，则支持的日期格式如下：

**注意**  
DDD 是指序数日期，它代表一年中从 001 到 365（闰年为 366）之间的某一天。例如，2024-002 代表 2024 年 1 月 2 日。
+ `yyyy-MM-dd`
+ `yyyyMMdd`
+ `yyyy-MM`
+ `yyyyMM`
+ `yyyy-DDD`
+ `yyyyDDD`
+ `yyyy`

如果选择了 Z 以外的时区，则支持的日期格式仅限于以下几种：
+ `yyyy-MM-dd`
+ `yyyy-DDD`
+ `yyyyDDD`

支持的日期范围为 1400-01-01 到 9999-12-31。

时间

如果不存在时区，或者时区为 UTC (Z)，则支持的时间格式如下：
+ `HH:mm:ss.SSS`
+ `HH:mm:ss`
+ `HHmmss.SSS`
+ `HHmmss`
+ `HH:mm`
+ `HHmm`
+ `HH`

如果选择了 Z 以外的时区，则支持的时间格式仅限于以下几种：
+ `HH:mm:ss`
+ `HH:mm:ss.SSS`

### Neptune openCypher 语言语义的差异
<a name="opencypher-compliance-semantics"></a>

Neptune 将节点和关系表示 IDs 为字符串而不是整数。ID 等于通过数据加载程序提供的 ID。如果该列有命名空间，则命名空间加上 ID。因此，`id` 函数返回的是字符串而不是整数。

`INTEGER` 数据类型限制为 64 位。使用 `TOINTEGER` 函数将较大的浮点值或字符串值转换为整数时，负值会被截断为 `LLONG_MIN`，正值被截断为 `LLONG_MAX`。

例如：

```
RETURN TOINTEGER(2^100)
>  9223372036854775807

RETURN TOINTEGER(-1 * 2^100)
>  -9223372036854775808
```

### 多值属性
<a name="openCypher-compliance-mvp"></a>

 虽然 openCypher CREATE 不会创建多值属性，但这种属性可能会存在于使用 Gremlin（Neptune 数据库）创建的数据中，也可能会在加载数据（Neptune 数据库和 Neptune Analytics）时存在。如果 Neptune openCypher 遇到多值属性，则会任意选择其中一个值，从而产生不确定的结果。

### NaN 值的处理
<a name="openCypher-compliance-handling-nan"></a>

 Neptune 对 `NaN` 属性值比较的处理是不明确的。依赖此类比较可能会导致意外或不确定的结果。