Amazon Neptune 中的 openCypher 扩展 - Amazon Neptune
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

Amazon Neptune 中的 openCypher 扩展

Amazon Neptune 支持 openCypher 规范参考版本 9。有关详细信息,请参阅 Amazon Neptune 中的 Amazon Neptune 中的 openCypher 规范合规性。此外,Amazon Neptune 支持此处列出的特征。除非提及特定版本,否则这些特征可在 Neptune 数据库和 Neptune Analytics 中使用。

Neptune 特定的 join() 函数

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

Neptune 实现了一个在 openCypher 规范中不存在的 join() 函数。它根据字符串文本列表和字符串分隔符创建字符串文本。此函数采用两个参数:

  • 第一个参数是字符串文本列表。

  • 第二个参数是分隔符字符串,可以包含零个、一个或多个字符。

示例:

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

Neptune 特定的 removeKeyFromMap() 函数

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

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

引擎版本 1.2.0.2 开始,Neptune 扩展了 openCypher 规范,以便您现在可以在 CREATEMERGEMATCH 子句中为节点和关系指定 id 值。这使您可以分配用户友好的字符串(而不是系统生成的 UUID)来识别节点和关系。

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

警告

openCypher 规范的这一扩展不向后兼容,因为 ~id 现在被视为保留的属性名称。如果您已经在数据和查询中将 ~id 用作属性,则需要将现有属性迁移到新的属性键并移除旧的属性键。请参阅如果您目前正在将 ~id 用作属性,该怎么办

以下示例展示了如何创建具有自定义 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 子句中使用多个自定义 ID 的示例:

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

如果您目前正在将 ~id 用作属性,该怎么办

引擎版本 1.2.0.2 中,openCypher 子句中的 ~id 键现在视为 id 而不是属性。这意味着,如果您有一个名为 ~id 的属性,则无法对其进行访问。

如果您使用的是 ~id 属性,那么在升级到引擎版本 1.2.0.2 或更高版本之前,您要做的就是先将现有 ~id 属性迁移到新的属性键,然后移除 ~id 属性。例如,下面的查询:

  • 为所有节点创建一个名为“newId”的新属性,

  • 将“~id”属性的值复制到“newId”属性中,

  • 并从数据中移除“~id”属性

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 子查询支持

在 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 执行的。执行内部查询时,ORDERLIMIT 子句是特定朋友居住的城市的本地子句,因此每个朋友可以获得(最多)两个城市。

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

CALL 子查询中的变量范围

CALL 子查询之前的子句中使用的变量必须由初始 WITH 子句导入。与常规 WITH 子句不同,它只能包含一系列变量,但不允许使用别名,也不能与 DISTINCTORDER BYWHERESKIPLIMIT 一起使用。

从 CALL 子查询返回的变量

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

限制

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

Neptune openCypher 函数

在 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?)

返回包含 firstsecond 交叉点中所有唯一元素的新列表。

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

排序函数

以下几节定义了对集合进行排序的函数。这些函数采用(在某些情况下是可选的)定义排序键和/或排序方向的 config 映射参数,或多个此类映射的列表:

{ 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" } }] }] }

时间函数

时间函数在 Neptune 版本 1.4.5.0 及更高版本中可用。

day

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

返回 datetimedate 值中月份的 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,因此 +08: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

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

返回 datetimedate 值(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,因此 +08: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

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

返回 datetimedate 值中的年份。对于 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,因此 +08: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 函数

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

reduce()

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