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 规范,以便您现在可以在 CREATE、MERGE 和 MATCH 子句中为节点和关系指定 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 执行的。执行内部查询时,ORDER 和 LIMIT 子句是特定朋友居住的城市的本地子句,因此每个朋友可以获得(最多)两个城市。
所有查询子句都可以在 CALL 子查询中使用。这也包括嵌套 CALL 子查询。第一个 WITH 子句和发出的变量存在一些限制,下文将对此进行说明。
CALL 子查询中的变量范围
CALL 子查询之前的子句中使用的变量必须由初始 WITH 子句导入。与常规 WITH 子句不同,它只能包含一系列变量,但不允许使用别名,也不能与 DISTINCT、ORDER BY、WHERE、SKIP 或 LIMIT 一起使用。
从 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?)
返回包含 first 和 second 交叉点中所有唯一元素的新列表。
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)
返回 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,因此 +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)
返回 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,因此 +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)
返回 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,因此 +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 }] }