

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

# Amazon Neptune 中的 SPARQL 标准合规性
<a name="feature-sparql-compliance"></a>

在列出了适用的 SPARQL 标准之后，以下各节提供有关 Neptune 的 SPARQL 实现如何扩展或偏离这些标准的具体细节。

**Topics**
+ [SPARQL 的适用标准](#feature-sparql-applicable-standards)
+ [Neptune SPARQL 中的默认命名空间前缀](#sparql-default-prefixes)
+ [SPARQL 默认图形和命名图形](#sparql-default-graph)
+ [Neptune 支持的 SPARQL XPath 构造函数](#access-graph-sparql-xpath-constructors)
+ [用于查询和更新的默认基本 IRI](#opencypher-compliance-default-iri)
+ [Neptune 中的 xsd:dateTime 值](#access-graph-sparql-xsd-date-time)
+ [Neptune 的特殊浮点值处理](#feature-overview-special-values-comparisons)
+ [Neptune 的价值限制 Arbitrary-Length](#feature-overview-arbitrary-length-values)
+ [Neptune 扩展了 SPARQL 中的等于比较](#feature-overview-sparql-not-equal)
+ [在 Neptune Out-of-Range SPARQL 中处理文字](#feature-overview-sparql-out-of-range)

在实施 SPARQL 图形查询语言时，Amazon Neptune 符合以下标准。

## SPARQL 的适用标准
<a name="feature-sparql-applicable-standards"></a>
+ SPARQL 根据 2013 年 3 月 21 日发布的 W3C [SPARQL 1.1 查询语言](https://www.w3.org/TR/sparql11-query/)建议定义。
+ SPARQL 更新协议和查询语言由 W3C [SPARQL 1.1 更新](https://www.w3.org/TR/sparql11-update/)规范定义。
+ [对于数字格式，SPARQL 遵循 [W3C XML 架构定义语言 (XSD) 1.1 第 2 部分：数据类型](https://www.w3.org/TR/xmlschema11-2/)规范，该规范与 IEEE 754 规范（IEEE 754-2019——IEEE 算术标准）一致。 Floating-Point ](https://standards.ieee.org/content/ieee-standards/en/standard/754-2019.html) 欲了解更多信息，另请参阅[维基百科（IEEE 754 页面](https://en.wikipedia.org/wiki/IEEE_754)）。但是，`IEEE 754-1985` 版本之后引入的功能不包括在该规范中。

## Neptune SPARQL 中的默认命名空间前缀
<a name="sparql-default-prefixes"></a>

默认情况下，Neptune 定义了以下前缀以用于 SPARQL 查询。有关更多信息，请参阅 SPARQL 规范中的[前缀名称](https://www.w3.org/TR/sparql11-query/#prefNames)。
+ `rdf`  – `http://www.w3.org/1999/02/22-rdf-syntax-ns#`
+ `rdfs` – `http://www.w3.org/2000/01/rdf-schema#`
+ `owl`  – `http://www.w3.org/2002/07/owl#`
+ `xsd`  – `http://www.w3.org/2001/XMLSchema#`

## SPARQL 默认图形和命名图形
<a name="sparql-default-graph"></a>

Amazon Neptune 将每个三元组与一个命名图形相关联。默认图形定义为所有命名图形的并集。

**查询的默认图形**  
如果提交 SPARQL 查询而未通过 `GRAPH` 关键字或 `FROM NAMED` 之类的构造明确指定图形，Neptune 将始终考虑数据库实例中的所有三元组。例如，以下查询从 Neptune SPARQL 端点返回所有三元组：

`SELECT * WHERE { ?s ?p ?o }`

显示在多个图形中的三元组将仅返回一次。

有关默认图形规范的信息，请参阅 SPARQL 1.1 查询语言规范的 [RDF 数据集](https://www.w3.org/TR/sparql11-query/#rdfDataset)一节。

**为加载、插入或更新指定命名图形**  
如果加载、插入或更新三元组时未指定命名图形，Neptune 使用 URI `http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph` 定义的回退命名图形。

使用基于三元组的格式发出 Neptune `Load` 请求时，可使用 `parserConfiguration: namedGraphUri` 参数指定命名图形以用于所有三元组。有关 `Load` 命令语法的信息，请参阅[Neptune 加载程序命令](load-api-reference-load.md)。

**重要**  
 如果您不使用此参数，并且未指定命名图形，将使用回退 URI：`http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph`。

如果通过 `SPARQL UPDATE` 加载三元组而未显式提供命名图形目标，也将使用此回退命名图形。

您可以使用基于四边形的格式 N-Quads 为数据库中的每个三元组指定一个命名图形。

**注意**  
使用 N-Quads 允许您将命名的图表留空。在本例中，将使用 `http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph`。  
您可以使用`namedGraphUri`解析器配置选项 N-Quads 来覆盖默认的命名图形。

## Neptune 支持的 SPARQL XPath 构造函数
<a name="access-graph-sparql-xpath-constructors"></a>

SPARQL 标准允许 SPARQL 引擎支持一组可扩展的 XPath 构造函数。Neptune 目前支持以下构造函数，其中 `xsd` 前缀定义为 `http://www.w3.org/2001/XMLSchema#`：
+ `xsd:boolean`
+ `xsd:integer`
+ `xsd:double`
+ `xsd:float`
+ `xsd:decimal`
+ `xsd:long`
+ `xsd:unsignedLong`

## 用于查询和更新的默认基本 IRI
<a name="opencypher-compliance-default-iri"></a>

由于 Neptune 集群有多个不同的端点，因此，将查询或更新的请求 URL 用作基本 IRI 可能会在解析相对 IRI 时导致意外结果。

从[引擎版本 1.2.1.0](engine-releases-1.2.1.0.md) 开始，如果请求中没有显式基本 IRI，Neptune 将使用 `http://aws.amazon.com/neptune/default/` 作为基本 IRI。

在以下请求中，基本 IRI 是请求的一部分：

```
BASE <http://example.org/default/>
INSERT DATA { <node1> <id> "n1" }

BASE <http://example.org/default/>
SELECT * { <node1> ?p ?o }
```

结果将是：

```
?p                                                   ?o
http://example.org/default/id                        n1
```

但是，此请求中不包括基本 IRI：

```
INSERT DATA { <node1> <id> "n1" }

SELECT * { <node1> ?p ?o }
```

在这种情况下，结果将是：

```
?p                                                   ?o
http://aws.amazon.com/neptune/default/id             n1
```

## Neptune 中的 xsd:dateTime 值
<a name="access-graph-sparql-xsd-date-time"></a>

出于性能考虑，Neptune 始终将 date/time 值存储为协调世界时 (UTC)。这可让直接比较非常有效。

此外，这意味着，如果您输入一个指定特定时区的 `dateTime` 值，则 Neptune 会将此值转换为 UTC 形式并丢弃该时区信息。当您稍后检索该 `dateTime` 值时，它会以 UTC 形式表示，而不是原始时区的时间，并且您再也无法确定原始时区。

## Neptune 的特殊浮点值处理
<a name="feature-overview-special-values-comparisons"></a>

Neptune 按如下所示处理 SPARQL 中的特殊浮点值。

### 在 Neptune 中处理 SPARQL NaN
<a name="feature-overview-NaN-comparisons"></a>

在 Neptune 中，SPARQL 可以接受查询中的 `NaN` 值。信号和安静 `NaN` 值之间没有区别。Neptune 将所有 `NaN` 值都视为安静值。

从语义上讲，无法进行 `NaN` 比较，因为没有什么大于、小于或等于 `NaN`。这意味着比较一侧的 `NaN` 值理论上永远不会匹配另一侧的*任何* 内容。

 但是，[XSD 规范](https://www.w3.org/TR/xmlschema-2/#double)确实将两个 `xsd:double` 或 `xsd:float` `NaN` 值视为相等。对于 `IN` 筛选条件、筛选表达式中的等于运算符以及完全匹配语义（在三元模式的对象位置具有 `NaN`），Neptune 遵循此规则。

### Neptune 中的 SPARQL 无限值处理
<a name="feature-overview-infinity-comparisons"></a>

在 Neptune 中，SPARQL 可以接受查询中的 `INF` 或 `-INF` 值。`INF` 的比较大于任何其它数值，而 `-INF` 的比较小于任何其它数值。

不管值的类型如何，带匹配符号的两个 INF 值的比较结果是相等（例如，浮点 `-INF` 等于双精度 `-INF`）。

当然，无法进行 `NaN` 比较，因为没有什么内容大于、小于或等于 `NaN`。

### Neptune 中的 SPARQL 负零处理
<a name="feature-overview-zero-comparisons"></a>

Neptune 将负零值标准化为无符号零。您可以在查询中使用负零值，但它们不会原样记录在数据库中，并且在比较时与无符号零相等。

## Neptune 的价值限制 Arbitrary-Length
<a name="feature-overview-arbitrary-length-values"></a>

Neptune 将 SPARQL 中的 XSD 整数、浮点数和十进制值的存储大小限制为 64 位。使用较大的值会导致 `InvalidNumericDataException` 错误。

## Neptune 扩展了 SPARQL 中的等于比较
<a name="feature-overview-sparql-not-equal"></a>

SPARQL 标准定义了值表达式的三元逻辑，其中值表达式可求值为 `true`、`false` 或 `error`。[SPARQL 1.1 规范](https://www.w3.org/TR/sparql11-query/#func-RDFterm-equal)中定义的术语相等的默认语义适用于 `FILTER` 条件下的 `=` 和 `!=` 比较，在比较规范的[运算符表](https://www.w3.org/TR/sparql11-query/#OperatorMapping)中不是明确可比较的数据类型时，会生成 `error`。

此行为可能会导致不直观的结果，如以下示例所示。

数据：

```
<http://example.com/Server/1> <http://example.com/ip> "127.0.0.1"^^<http://example.com/datatype/IPAddress>
```

查询 1：

```
SELECT * WHERE {
    <http://example.com/Server/1> <http://example.com/ip> ?o .
    FILTER(?o = "127.0.0.2"^^<http://example.com/datatype/IPAddress>)
}
```

查询 2：

```
SELECT * WHERE {
    <http://example.com/Server/1> <http://example.com/ip> ?o .
    FILTER(?o != "127.0.0.2"^^<http://example.com/datatype/IPAddress>)
}
```

借助 Neptune 在版本 1.0.2.1 之前使用的默认 SPARQL 语义，两个查询均返回空结果。原因是，`?o = "127.0.0.2"^^<http://example.com/IPAddress>` 在为 `?o := "127.0.0.1"^^<http://example.com/IPAddress>` 评估时生成 `error` 而不是 `false`，因为没有为自定义数据类型 `<http://example.com/IPAddress>` 指定明确的比较规则。因此，第二个查询中的否定版本也会生成 `error`。在这两个查询中，`error` 会导致筛选掉候选解决方案。

从版本 1.0.2.1 开始，Neptune 根据规范，扩展了 SPARQL 不等于运算符。请参阅 [SPARQL 1.1 关于运算符可扩展性的部分](https://www.w3.org/TR/sparql11-query/#operatorExtensibility)，该部分允许引擎定义如何对用户定义的数据类型和不可比较的内置数据类型进行比较的其他规则。

利用此选项，Neptune 现在对在运算符映射表中未显式定义的任意两种数据类型进行比较时，如果文本值和数据类型在语法上相等，则视为 `true`，否则视为 false。在任何情况下都不会产生 `error`。

使用这些新语义，第二个查询将返回 `"127.0.0.1"^^<http://example.com/IPAddress>` 而不是空的结果。

## 在 Neptune Out-of-Range SPARQL 中处理文字
<a name="feature-overview-sparql-out-of-range"></a>

XSD 语义定义每个数字类型及其值空间（`integer` 和 `decimal` 除外）。这些定义将每种类型限制为一个值范围。例如，`xsd:byte` 范围是从 -128 到 \+127（含）。超出此范围的任何值都被视为无效。

如果您尝试在类型的值空间之外分配文本值（例如，如果您尝试将 `xsd:byte` 设置为文本值 999），则 Neptune 按原样接受超出范围的值，而不会舍入或截断该值。但它不会将该值保留为数字值，因为给定的类型无法表示数字值。

也就是说，即使 `"999"^^xsd:byte` 是一个超出定义的 `xsd:byte` 值范围的值，Neptune 也可以接受它。但是，在数据库中保留该值后，它只能在三元模式的宾语位置用于完全匹配语义。不能对其执行范围过滤器，因为超出范围的文字不被视为数值。

SPARQL 1.1 规范以 `numeric`*-operator-*`numeric`、`string`*-operator-*`string`、`literal`*-operator-*`literal` 等形式定义[范围运算符](https://www.w3.org/TR/sparql11-query/#OperatorMapping)。Neptune 无法执行诸如 `invalid-literal`*-operator-*`numeric-value` 之类的范围比较运算符。