本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
Amazon Neptune 中的 openCypher 标准合规性
Amazon Neptune 版本的 openCypher 通常支持当前 openCypher 规范(即 Cypher 查询语言参考版本 9
注意
Cypher 的当前 Neo4j 实现包含上述 openCypher 规范中未包含的功能。如果您要将当前 Cypher 代码迁移到 Neptune,请参阅Neptune 与 Neo4j 的兼容性和重写 Cypher 查询以在 Neptune 上的 openCypher 中运行以了解更多信息。
Neptune 中对 openCypher 子句的支持
除非另有说明,否则 Neptune 支持以下子句:
MATCH
– 支持,但除了目前不支持
和shortestPath()
之外。allShortestPaths()
OPTIONAL MATCH
–Neptune 目前不支持。但是,Neptune 确实支持在MANDATORY MATCH
MATCH
查询中使用自定义 ID 值。-
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 值。DELETE
SET
REMOVE
MERGE
– Neptune 支持在MERGE
查询中使用自定义 ID 值。
–Neptune 目前不支持。CALL[YIELD...]
UNION, UNION ALL
– 支持只读查询,但目前不支持突变查询。
Neptune 中对 openCypher 运算符的支持
除非另有说明,否则 Neptune 支持以下运算符:
一般运算符
DISTINCT
用于访问嵌套文本映射的属性的
.
运算符。
数学运算
+
加法运算符。-
减法运算符。*
乘法运算符。/
除法运算符。%
模除运算符。不支持
^
幂运算符。
比较运算符
=
加法运算符。<>
不等于运算符。支持
<
小于运算符,除非其中一个参数是路径、列表或映射。支持
>
大于运算符,除非其中一个参数是路径、列表或映射。支持
<=
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 表达式的支持
除非另有说明,否则 Neptune 支持以下表达式:
CASE
-
Neptune 目前不支持使用
[]
表达式来访问节点、关系或映射中动态计算的属性键。例如,以下内容不起作用:MATCH (n) WITH [5, n, {key: 'value'}] AS list RETURN list[1].name
Neptune 中对 openCypher 函数的支持
除非另有说明,否则 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()(将列表中的字符串联接成单个字符串)
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()(将列表中的字符串联接成单个字符串)
left()
lTrim()
replace()
reverse()
right()
rTrim()
split()
substring()
toLower()
toString()
toUpper()
trim()
用户定义的函数
Neptune 中目前不支持用户定义的函数
。
Neptune 特定的 openCypher 实现细节
以下各节描述了 openCypher 的 Neptune 实现可能与 openCypher 规范
Neptune 中的可变长度路径 (VLP) 求值
可变长度路径 (VLP
) 求值会发现图形中节点之间的路径。查询中的路径长度可以不受限制。为了防止循环,openCypher 规范
对于 VLP,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 目前为 openCypher 中的时间函数提供有限支持。它支持对时间类型使用 DateTime
数据类型。
datetime()
函数可用于获取当前的 UTC 日期和时间,如下所示:
RETURN datetime() as res
可以从存储在 Neptune 中的数据转换日期和时间值,如下所示:
MATCH (n) RETURN datetime(n.createdDate)
日期和时间值可以从 "
dateT
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 中的所有日期/时间值均作为 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 将节点和关系 ID 表示为字符串而不是整数。ID 等于通过数据加载程序提供的 ID。如果该列有命名空间,则命名空间加上 ID。因此,id
函数返回的是字符串而不是整数。
INTEGER
数据类型限制为 64 位。使用 TOINTEGER
函数将较大的浮点值或字符串值转换为整数时,负值会被截断为 LLONG_MIN
,正值被截断为 LLONG_MAX
。
例如:
RETURN TOINTEGER(2^100) > 9223372036854775807 RETURN TOINTEGER(-1 * 2^100) > -9223372036854775808
Neptune 特定的 join()
函数
Neptune 实现了一个在 openCypher 规范中不存在的 join()
函数。它根据字符串文本列表和字符串分隔符创建字符串文本。此函数采用两个参数:
第一个参数是字符串文本列表。
第二个参数是分隔符字符串,可以包含零个、一个或多个字符。
例如:
join(["abc", "def", "ghi"], ", ") // Returns "abc, def, ghi"
Neptune 特定的 removeKeyFromMap()
函数
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 值
从引擎版本 1.2.0.2 开始,Neptune 扩展了 openCypher 规范,以便您现在可以在 CREATE
、MERGE
和 MATCH
子句中为节点和关系指定 id
值。这使您可以分配用户友好的字符串(而不是系统生成的 UUID)来识别节点和关系。
警告
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 openCypher 和 Cypher 之间的其它区别
Neptune 仅对于 Bolt 协议支持 TCP 连接。 WebSockets不支持螺栓连接。
Neptune openCypher 会移除 Unicode 在
trim()
、ltrim()
和rtrim()
函数中定义的空格。在 Neptune openCypher 中,对于较大的双精度值,
tostring(
double)
不会自动切换到 E 表示法。尽管 openCypher CREATE 不会创建多值属性,但它们可以存在于使用 Gremlin 创建的数据中。如果 Neptune openCypher 遇到多值属性,则会任意选择其中一个值,从而产生不确定的结果。