

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

# Amazon Neptune 中的 openCypher 扩展
<a name="access-graph-opencypher-extensions"></a>

 Amazon Neptune 支持 openCypher 规范参考版本 9。有关详细信息，请参阅 Amazon Neptune 中的 [Amazon Neptune 中的 openCypher 规范合规性](feature-opencypher-compliance.md)。此外，Amazon Neptune 支持此处列出的功能。除非提及特定版本，否则这些功能可在 Neptune 数据库和 Neptune Analytics 中使用。

## 查询时 S3 数据访问权限
<a name="opencypher-compliance-neptune-read"></a>

在 Neptune 数据库 1.4.7.0 及更高版本中可用。

Neptune 支持在 OpenCypher 查询中直接从亚马逊 S3 读取 CSV 或 Parquet 数据的`neptune.read()`功能。与在查询之前导入数据的批量加载器不同，它在执行查询时`neptune.read()`访问 Amazon S3 数据。

有关完整的文档，请参阅[neptune.read ()](access-graph-opencypher-21-extensions-s3-read.md)。

## Neptune 特定的 `join()` 函数
<a name="opencypher-compliance-join-function"></a>

在 Neptune 数据库和 Neptune Analytics 中可用。

Neptune 实现了一个在 openCypher 规范中不存在的 `join()` 函数。它根据字符串文本列表和字符串分隔符创建字符串文本。此函数采用两个参数：
+ 第一个参数是字符串文本列表。
+ 第二个参数是分隔符字符串，可以包含零个、一个或多个字符。

示例：

```
join(["abc", "def", "ghi"], ", ")    // Returns "abc, def, ghi"
```

## Neptune 特定的 `removeKeyFromMap()` 函数
<a name="opencypher-compliance-removeKeyFromMap-function"></a>

在 Neptune 数据库和 Neptune Analytics 中可用。

Neptune 实现了一个在 openCypher 规范中不存在的 `removeKeyFromMap()` 函数。它从映射中移除指定的键并返回生成的新映射。

此函数采用两个参数：
+ 第一个参数是从中移除键的映射。
+ 第二个参数是从映射中移除的键。

当您想通过展开映射列表来设置节点或关系的值时，`removeKeyFromMap()` 函数特别有用。例如：

```
UNWIND [{`~id`: 'id1', name: 'john'}, {`~id`: 'id2', name: 'jim'}] as val
CREATE (n {`~id`: val.`~id`})
SET n = removeKeyFromMap(val, '~id')
```

## 节点和关系属性的自定义 ID 值
<a name="opencypher-compliance-custom-ids"></a>

在 Neptune 数据库 1.2.0.2 及更高版本和 Neptune Analytics 中可用。

从[引擎版本 1.2.0.2](engine-releases-1.2.0.2.md) 开始，Neptune 扩展了 openCypher 规范，以便您现在可以在 `CREATE`、`MERGE` 和 `MATCH` 子句中为节点和关系指定 `id` 值。这使您可以分配用户友好的字符串，而不是系统生成的字符串 UUIDs ，以识别节点和关系。

在 Neptune Analytics 中，自定义 ID 值不适用于边缘。

**警告**  
openCypher 规范的这一扩展不向后兼容，因为 `~id` 现在被视为保留的属性名称。如果您已经在数据和查询中将 `~id` 用作属性，则需要将现有属性迁移到新的属性键并移除旧的属性键。请参阅[如果您目前正在将 `~id` 用作属性，该怎么办](#opencypher-compliance-custom-ids-migrating)。

以下示例展示了如何创建具有自定义 ID 的节点和关系：

```
CREATE (n {`~id`: 'fromNode', name: 'john'})
  -[:knows {`~id`: 'john-knows->jim', since: 2020}]
  ->(m {`~id`: 'toNode', name: 'jim'})
```

如果您尝试创建已在使用的自定义 ID，Neptune 会引发 `DuplicateDataException` 错误。

以下是在 `MATCH` 子句中使用一个自定义 ID 的示例：

```
MATCH (n {`~id`: 'id1'})
RETURN n
```

以下是在子`MERGE`句中使用 custom IDs 的示例：

```
MATCH (n {name: 'john'}), (m {name: 'jim'})
MERGE (n)-[r {`~id`: 'john->jim'}]->(m)
RETURN r
```

### 如果您目前正在将 `~id` 用作属性，该怎么办
<a name="opencypher-compliance-custom-ids-migrating"></a>

在[引擎版本 1.2.0.2](engine-releases-1.2.0.2.md) 中，openCypher 子句中的 `~id` 键现在视为 `id` 而不是属性。这意味着，如果您有一个名为 `~id` 的属性，则无法对其进行访问。

如果您使用的是 `~id` 属性，那么在升级到引擎版本 `1.2.0.2` 或更高版本之前，您要做的就是先将现有 `~id` 属性迁移到新的属性键，然后移除 `~id` 属性。例如，下面的查询：
+ 为所有节点创建一个名为“newId”的新属性，
+ 将“\$1id”属性的值复制到“newId”属性中，
+ 并从数据中移除“\$1id”属性

```
MATCH (n)
WHERE exists(n.`~id`)
SET n.newId = n.`~id`
REMOVE n.`~id`
```

对于数据中具有 `~id` 属性的任何关系，都需要做同样的事情。

您还必须更改您正在使用的任何引用 `~id` 属性的查询。例如，此查询：

```
MATCH (n)
WHERE n.`~id` = 'some-value'
RETURN n
```

...会改成这样：

```
MATCH (n)
WHERE n.newId = 'some-value'
RETURN n
```

## 在 Neptune 中提供 CALL 子查询支持
<a name="call-subquery-support"></a>

 在 Neptune 数据库 1.4.1.0 及更高版本和 Neptune Analytics 中可用。

 Amazon Neptune 支持 `CALL` 子查询。`CALL` 子查询是主查询的一部分，对于 `CALL` 子查询的每个输入，它在隔离的范围中运行。

 例如，假设图形包含有关人员、他们的朋友和他们居住的城市的数据，我们可以使用 `CALL` 子查询来检索某人的每个朋友居住的两个最大的城市：

```
MATCH (person:Person)-[:knows]->(friend) 
CALL { 
  WITH friend 
  MATCH (friend)-[:lived_in]->(city) 
  RETURN city 
  ORDER BY city.population DESC
  LIMIT 2 
} 
RETURN person, friend, city
```

 在此示例中，`CALL { ... }` 中的查询部分是针对与前面的 MATCH 子句匹配的每个 `friend` 执行的。执行内部查询时，`ORDER` 和 `LIMIT` 子句是特定朋友居住的城市的本地子句，因此每个朋友可以获得（最多）两个城市。

 所有查询子句都可以在 `CALL` 子查询中使用。这也包括嵌套 `CALL` 子查询。第一个 `WITH` 子句和发出的变量存在一些限制，下文将对此进行说明。

### CALL 子查询中的变量范围
<a name="variable-scope-inside-call-subquery"></a>

 `CALL` 子查询之前的子句中使用的变量必须由初始 `WITH` 子句导入。与常规 `WITH` 子句不同，它只能包含一系列变量，但不允许使用别名，也不能与 `DISTINCT`、`ORDER BY`、`WHERE`、`SKIP` 或 `LIMIT` 一起使用。

### 从 CALL 子查询返回的变量
<a name="variables-returned-call-subquery"></a>

 `CALL` 子查询中发出的变量由最后的 `RETURN` 子句指定。请注意，发出的变量不能与 `CALL` 子查询之前的变量重叠。

### 限制
<a name="call-subquery-limitations"></a>

 目前，不支持 `CALL` 子查询中的更新。

## Neptune openCypher 函数
<a name="opencypher-compliance-new-functions"></a>

 在 Neptune 数据库 1.4.1.0 及更高版本和 Neptune Analytics 中可用。

**textIndexOf**

 `textIndexOf(text :: STRING, lookup :: STRING, from = 0 :: INTEGER?, to = -1 :: INTEGER?) :: (INTEGER?)` 

 返回从偏移 `from`（包含）到偏移 `to`（排除）的 `text` 范围内首次出现 `lookup` 的索引。如果 `to` 为 -1，则范围一直延续到 `text` 的末尾。索引从零开始，以 Unicode 标量值（非代理代码点）表示。

```
RETURN textIndexOf('Amazon Neptune', 'e')
{
  "results": [{
      "textIndexOf('Amazon Neptune', 'e')": 8
    }]
}
```

**collToSet**

 `collToSet(values :: LIST OF ANY?) :: (LIST? OF ANY?)` 

 返回仅包含原始列表中唯一元素的新列表。**保持**原始列表的顺序（例如 `[1, 6, 5, 1, 5]` 返回 `[1, 6, 5]`）。

```
RETURN collToSet([1, 6, 5, 1, 1, 5])
{
  "results": [{
      "collToSet([1, 6, 5, 1, 1, 5])": [1, 6, 5]
    }]
}
```

**collSubtract**

 `collSubtract(first :: LIST OF ANY?, second :: LIST OF ANY?) :: (LIST? OF ANY?)` 

 返回包含 `first` 中所有唯一元素且排除 `second` 中元素的新列表。

```
RETURN collSubtract([2, 5, 1, 0], [1, 5])
{
  "results": [{
      "collSubtract([2, 5, 1, 0], [1, 5])": [0, 2]
    }]
}
```

**collIntersection**

 `collIntersection(first :: LIST? OF ANY?, second :: LIST? OF ANY?) :: (LIST? OF ANY?)` 

 返回包含 `first` 和 `second` 交叉点中所有唯一元素的新列表。

```
RETURN collIntersection([2, 5, 1, 0], [1, 5])
{
  "results": [{
      "collIntersection([2, 5, 1, 0], [1, 5])": [1, 5]
    }]
}
```

## 排序函数
<a name="sorting-functions"></a>

 以下几节定义了对集合进行排序的函数。这些函数采用（在某些情况下是可选的）`config`映射参数，或者多个此类映射的列表，这些映射定义了排序键 and/or 的排序方向：

```
{ key: STRING, order: STRING }
```

 在此示例中，`key` 是映射或节点属性，其值用于排序。`order` 是“`asc`”或“`desc`”（不区分大小写），分别用于指定升序或降序排序。默认情况下，将按升序进行排序。

**collSort**

 `collSort(coll :: LIST OF ANY, config :: MAP?) :: (LIST? OF ANY?)` 

 返回包含 `coll` 输入列表中元素的新排序列表。

```
RETURN collSort([5, 3, 1], {order: 'asc'})
{
  "results": [{
      "collSort([5, 3, 1])": [1, 3, 5]
    }]
}
```

**collSortMaps**

 `collSortMaps(coll :: LIST OF MAP, config :: MAP) :: (LIST? OF ANY?)` 

 返回按指定 `key` 属性的值排序的映射列表。

```
RETURN collSortMaps([{name: 'Alice', age: 25}, {name: 'Bob', age: 35}, {name: 'Charlie', age: 18}], {key: 'age', order: 'desc'})
{
  "results": [{
      "x": [{
          "age": 35,
          "name": "Bob"
        }, {
          "age": 25,
          "name": "Alice"
        }, {
          "age": 18,
          "name": "Charlie"
        }]
    }]
}
```

**collSortMulti**

```
collSortMulti(coll :: LIST OF MAP?, 
configs = [] :: LIST OF MAP, 
limit = -1 :: INTEGER?, 
skip = 0 :: INTEGER?) :: (LIST? OF ANY?)
```

 返回按指定 `key` 属性的值排序的映射列表，可以选择应用限制和跳过。

```
RETURN collSortMulti([{name: 'Alice', age: 25}, {name: 'Bob', age: 35}, {name: 'Charlie', age: 18}], [{key: 'age', order: 'desc'}, {key:'name'}]) as x
{
  "results": [{
      "x": [{
          "age": 35,
          "name": "Bob"
        }, {
          "age": 25,
          "name": "Alice"
        }, {
          "age": 18,
          "name": "Charlie"
        }]
    }]
}
```

**collSortNodes**

 `collSortNodes(coll :: LIST OF NODE, config :: MAP) :: (LIST? OF NODE?)` 

 返回 `coll` 输入列表的排序版本，按节点元素各自 `key` 属性的值对节点元素进行排序。

```
create (n:person {name: 'Alice', age: 23}), (m:person {name: 'Eve', age: 21}), (o:person {name:'Bob', age:25})
{"results":[]}

match (n:person) with collect(n) as people return collSortNodes(people, {key: 'name', order: 'desc'})
{
  "results": [{
      "collSortNodes(people, 'name')": [{
          "~id": "e599240a-8c23-4337-8aa8-f603c8fb5488",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 21,
            "name": "Eve"
          }
        }, {
          "~id": "8a6ef785-59e3-4a0b-a0ff-389655a9c4e6",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 25,
            "name": "Bob"
          }
        }, {
          "~id": "466bc826-f47f-452c-8a27-6b7bdf7ae9b4",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 23,
            "name": "Alice"
          }
        }]
    }]
}

match (n:person) with collect(n) as people return collSortNodes(people, {key: 'age'})
{
  "results": [{
      "collSortNodes(people, '^age')": [{
          "~id": "e599240a-8c23-4337-8aa8-f603c8fb5488",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 21,
            "name": "Eve"
          }
        }, {
          "~id": "466bc826-f47f-452c-8a27-6b7bdf7ae9b4",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 23,
            "name": "Alice"
          }
        }, {
          "~id": "8a6ef785-59e3-4a0b-a0ff-389655a9c4e6",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 25,
            "name": "Bob"
          }
        }]
    }]
}
```

## 时间函数
<a name="temporal-functions"></a>

 时间函数在 Neptune 版本 [1.4.5.0](https://docs.aws.amazon.com/releases/release-1.4.5.0.xml) 及更高版本中可用。

### day
<a name="temporal-functions-day"></a>

 `day(temporal :: (datetime | date)) :: (LONG)` 

 返回 `datetime` 或 `date` 值中月份的 `day`。对于 `datetime`：在提取日期之前，根据输入将值标准化为 UTC。对于 `date`：根据时区提取日期。

 `datetime` 输入在 Neptune 数据库和 Neptune Analytics 中均可用：

```
RETURN day(datetime('2021-06-03T01:48:14Z'))
{
  "results": [{
      "day(datetime('2021-06-03T01:48:14Z'))": 3
    }]
}
```

 在此示例中，`datetime` 被标准化为 UTC，因此 \$108:00 向后移动到 6 月 2 日。

```
RETURN day(datetime('2021-06-03T00:00:00+08:00'))
{
  "results": [{
      "day(datetime('2021-06-03T00:00:00+08:00'))": 2
    }]
}
```

 `date` 输入仅在 Neptune Analytics 中可用：

```
RETURN day(date('2021-06-03Z'))
{
  "results": [{
      "day(date('2021-06-03Z'))": 3
    }]
}
```

 `date` 保留时区，保持在 6 月 3 日。

```
RETURN day(date('2021-06-03+08:00'))
{
  "results": [{
      "day(date('2021-06-03+08:00'))": 3
    }]
}
```

### month
<a name="temporal-functions-month"></a>

 `month(temporal :: (datetime | date)) :: (LONG)` 

 返回 `datetime` 或 `date` 值（1-12）中的月份。对于 `datetime`：在提取月份之前，根据输入将值标准化为 UTC。对于 `date`：根据时区提取月份。

 `datetime` 输入在 Neptune 数据库和 Neptune Analytics 中均可用：

```
RETURN month(datetime('2021-06-03T01:48:14Z'))
{
  "results": [{
      "month(datetime('2021-06-03T01:48:14Z'))": 6
    }]
}
```

 在此示例中，`datetime` 被标准化为 UTC，因此 \$108:00 向后移动到 5 月 31 日。

```
RETURN month(datetime('2021-06-01T00:00:00+08:00'))
{
  "results": [{
      "month(datetime('2021-06-01T00:00:00+08:00'))": 5
    }]
}
```

 `date` 输入仅在 Neptune Analytics 中可用：

```
RETURN month(date('2021-06-03Z'))
{
  "results": [{
      "month(date('2021-06-03Z'))": 6
    }]
}
```

 `date` 保留时区，保持在 6 月 1 日。

```
RETURN month(date('2021-06-01+08:00'))
{
  "results": [{
      "month(date('2021-06-01+08:00'))": 6
    }]
}
```

### year
<a name="temporal-functions-year"></a>

 `year(temporal :: (datetime | date)) :: (LONG)` 

 返回 `datetime` 或 `date` 值中的年份。对于 `datetime`：在提取年份之前，根据输入将值标准化为 UTC。对于 `date`：根据时区提取年份。

 `datetime` 输入在 Neptune 数据库和 Neptune Analytics 中均可用：

```
RETURN year(datetime('2021-06-03T01:48:14Z'))
{
  "results": [{
      "year(datetime('2021-06-03T01:48:14Z'))": 2021
    }]
}
```

 在此示例中，`datetime` 被标准化为 UTC，因此 \$108:00 向后移动到 2020 年 12 月 31 日。

```
RETURN year(datetime('2021-01-01T00:00:00+08:00'))
{
  "results": [{
      "year(datetime('2021-01-01T00:00:00+08:00'))": 2020
    }]
}
```

 `date` 输入仅在 Neptune Analytics 中可用：

```
RETURN year(date('2021-06-03Z'))
{
  "results": [{
      "year(date('2021-06-03Z'))": 2021
    }]
}
```

 `date` 保留时区，保持在 2021 年 6 月。

```
RETURN year(date('2021-01-01+08:00'))
{
  "results": [{
      "year(date('2021-01-01+08:00'))": 2021
    }]
}
```

### Neptune openCypher 函数
<a name="openCypher-functions"></a>

 在 Neptune 数据库 1.4.6.0 及更高版本和 Neptune Analytics 中可用。

#### reduce()
<a name="openCypher-functions-reduce"></a>

 reduce 通过将每个列表元素与运行总数或“累加器”组合来按顺序处理每个列表元素。它从初始值开始，在每次操作后更新累加器，并在下一次迭代中使用该更新的值。

 `for i in (0, ..., n) acc = acc X list[I], where X denotes any binary operator` 

 处理完所有元素后，它会返回最终的累加结果。

 典型的 reduce() 结构是：`reduce(accumulator = initial , variable IN list | expression)`

**类型规格：**  
 `- initial: starting value for the accumulator :: (Long | FLOAT | STRING | LIST? OF (STRING, LONG, FLOAT)) - list: the input list :: LIST OF T where T matches initial type - variable :: represents each element in the input list - expression :: Only supports '+' and '*' operator - return :: Same type as initial ` 

**限制：**  
 目前，`reduce()` 表达式仅支持：
+  数值乘法 
+  数值加法 
+  字符串连接 
+  列表连接 

 它们由 `+` 或 `*` 运算符表示。该表达式应为二进制表达式，如下所示：`expression pattern: accumulator + any variable or accumulator * any variable`

**溢出处理：**  
 Neptune 会在 `reduce()` 评估期间检测数值溢出问题，并根据数据类型做出不同的响应：

```
LONG (signed 64‑bit)
--------------------
• Valid range: –9 223 372 036 854 775 808 … 9 223 372 036 854 775 807  
• If any intermediate or final value falls outside this range,
  Neptune aborts the query with long overflow error message.
  
FLOAT (IEEE‑754 double)
-----------------------
• Largest finite value ≈ 1.79 × 10^308  
• Larger results overflow to INF
  Once `INF` is produced, it propagates through the remainder
  of the reduction.
```

**示例：**  
有关 reduce() 函数的信息，请参阅以下示例。

```
1. Long Addition:
RETURN reduce(sum = 0, n IN [1, 2, 3] | sum + n)
{
  "results": [{
      "reduce(sum = 0, n IN [1, 2, 3] | sum + n)": 6
    }]
}

2. String Concatenation:
RETURN reduce(str = "", x IN ["A", "B", "C"] | str + x) 
{
  "results": [{
      "reduce(str = "", x IN ["A", "B", "C"] | str + x)": "ABC"
    }]
}

3. List Combination:
RETURN reduce(lst = [], x IN [1, 2, 3] | lst + x)
{
  "results": [{
      "reduce(lst = [], x IN [1, 2, 3] | lst + x)": [1, 2, 3]
    }]
}

4. Float Addition:
RETURN reduce(total = 0.0, x IN [1.5, 2.5, 3.5] | total + x) 
{
  "results": [{
      "reduce(total = 0.0, x IN [1.5, 2.5, 3.5] | total + x)": 7.5
    }]
}

5. Long Multiplication:
RETURN reduce(product = 1, n IN [1, 2, 3] | product * n)
{
  "results": [{
      "reduce(product = 0, n IN [1, 2, 3] | product * n)": 6
    }]
}

6. Float Multiplication:
RETURN reduce(product = 1.0, n IN [1.5, 2.5, 3.5] | product * n)
{
  "results": [{
      "reduce(product = 1.0, n IN [1.5, 2.5, 3.5] | product * n)": 13.125
    }]
}

7. Long Overflow (Exception):
RETURN reduce(s = 9223372036854775807, x IN [2, 3] | s * x) AS result
{
"results": [{
    "reduce(s = 9223372036854775807, x IN [2, 3] | s * x) AS result": long overflow
    }]
}

8. Float Overflow:
RETURN reduce(s = 9.0e307, x IN [8.0e307, 1.0e307] | s + x) AS result
{
"results": [{
    "reduce(s = 9.0e307, x IN [8.0e307, 1.0e307] | s + x) AS result": INF
    }]
}
```