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

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

Amazon Neptune 中的 openCypher 标准合规性

Amazon Neptune 版本的 openCypher 通常支持当前 openCypher 规范(即 Cypher 查询语言参考版本 9)中定义的子句、运算符、表达式、函数和语法。下面列出了 Neptune 对 openCypher 的支持的局限性和差异。

注意

Cypher 的当前 Neo4j 实现包含上述 openCypher 规范中未包含的功能。如果您要将当前 Cypher 代码迁移到 Neptune,请参阅Neptune 与 Neo4j 的兼容性重写 Cypher 查询以在 Neptune 上的 openCypher 中运行以了解更多信息。

Neptune 中对 openCypher 子句的支持

除非另有说明,否则 Neptune 支持以下子句:

  • MATCH – 支持,但除了目前不支持 shortestPath()allShortestPaths() 之外。

  • OPTIONAL MATCH

  • MANDATORY MATCH –Neptune 目前支持。但是,Neptune 确实支持在 MATCH 查询中使用自定义 ID 值

  • RETURN – 支持,但与 SKIPLIMIT 的非静态值结合使用时除外。例如,以下内容目前不起作用:

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

    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 值

  • CALL[YIELD...] –Neptune 目前支持。

  • 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)

日期和时间值可以从 "dateTtime" 格式的字符串中解析,其中 datetime 都以下面支持的形式之一表示:

支持的日期格式
  • 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 转换为 epochmillisepochmillis() 函数。例如:

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 规范,以便您现在可以在 CREATEMERGEMATCH 子句中为节点和关系指定 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 遇到多值属性,则会任意选择其中一个值,从而产生不确定的结果。