

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

# 从 Neo4j 到 Neptune 的数据迁移
<a name="migration-data-migration"></a>

在从 Neo4j 迁移到 Amazon Neptune 时，迁移数据是该过程中的一个主要步骤。有多种迁移数据的方法。正确的方法取决于应用程序的需求、数据大小和所需的迁移类型。但是，其中许多迁移都需要对相同的注意事项进行评测，下文将重点介绍其中一些注意事项。

**注意**  
有关如何执行离线数据迁移的一个示例的完整分步演练，请参阅 [Amazon 数据库博客](https://www.amazonaws.cn/blogs/?awsf.blog-master-category=category%23database)中的[使用全自动实用程序将 Neo4j 图形数据库迁移到 Neptune](https://www.amazonaws.cn/blogs/database/migrating-a-neo4j-graph-database-to-amazon-neptune-with-a-fully-automated-utility/)。

## 评测从 Neo4j 到 Neptune 的数据迁移
<a name="migration-data-assessment"></a>

评测任何数据迁移的第一步是确定如何迁移数据。这些选项取决于要迁移的应用程序的架构、数据大小和迁移期间的可用性需求。通常，迁移往往分为两种类别之一：在线或离线。

离线迁移往往是最容易完成的，因为应用程序在迁移期间不接受读取或写入流量。应用程序停止接受流量后，可以在重新启用应用程序之前导出、优化、导入数据并测试应用程序。

在线迁移则更复杂，因为在迁移数据时，应用程序仍需要接受读取和写入流量。每次在线迁移的确切需求可能有所不同，但总体架构通常类似于以下架构：
+ 需要通过[将 Neo4j 流配置为 Kafka 集群的源](https://neo4j.com/labs/kafka/4.0/producer/)，在 Neo4j 中启用对数据库进行持续更改的源。
+ 完成此操作后，可以按照[迁移到 Neptune 时从 Neo4j 导出数据](#migration-data-exporting)中的说明导出正在运行的系统，并注明稍后与 Kafka 主题相关的时间。
+ 然后，按照[迁移到 Neptune 时从 Neo4j 导入数据](#migration-data-importing)中的说明将导出的数据导入到 Neptune 中。
+ 然后，可以使用类似于[从 Amazon Kinesis Data Streams 写入 Amazon Neptune](https://github.com/aws-samples/amazon-neptune-samples/tree/master/gremlin/stream-2-neptune) 中描述的架构，将来自 Kafka 流的已更改数据复制到 Neptune 集群。请注意，更改复制可以并行运行，以验证新的应用程序架构和性能。
+ 验证数据迁移后，可以将应用程序流量重定向到 Neptune 集群，并且可以停用 Neo4j 实例。

## 从 Neo4j 迁移到 Neptune 的数据模型优化
<a name="migration-data-model-optimization"></a>

Neptune 和 Neo4j 都支持已标注的属性图 (LPG)。但是，Neptune 有一些架构和数据模型的差异，您可以利用这些差异来优化性能：

### 优化节点和边缘 ID
<a name="migration-data-node-edge-id-optimization"></a>

Neo4j 会自动生成数字长型 ID。使用 Cypher，您可以通过 ID 引用节点，但通常不鼓励这样做，而倾向于通过索引属性查找节点。

Neptune 允许您[为顶点和边缘提供自己的基于字符串的 ID](access-graph-gremlin-differences.md#feature-gremlin-differences-user-supplied-ids)。如果您不提供自己的 ID，Neptune 会自动为新的边缘和顶点生成 UUID 的字符串表示形式。

如果您通过从 Neo4j 导出数据，然后批量导入到 Neptune，以便将数据从 Neo4j 迁移到 Neptune，则可以保留 Neo4j 的 ID。Neo4j 生成的数值在导入到 Neptune 时可以用作用户提供的 ID，在 Neptune 中，它们以字符串而不是数值表示。

但是，在某些情况下，您可能需要将顶点属性提升为顶点 ID。正如使用索引属性查找节点是在 Neo4j 中查找节点的最快方法一样，通过 ID 查找顶点也是在 Neptune 中找到顶点的最快方法。因此，如果您能识别出包含唯一值的合适顶点属性，您应该考虑在大容量加载 CSV 文件中用指定的属性值替换顶点 \~id。如果您这样做，您还必须在 CSV 文件中重写任何相应的 \~from 和 \~to 边缘值。

### 将数据从 Neo4j 迁移到 Neptune 时的架构约束
<a name="migration-data-schema-constraints"></a>

在 Neptune 中，唯一可用的架构约束是节点或边缘的 ID 的唯一性。鼓励需要利用唯一性约束的应用程序考虑使用这种方法，通过指定节点或边缘 ID 来实现唯一性约束。如果应用程序使用多列作为唯一性约束，则可以将 ID 设置为这些值的组合。例如，`id=123, code='SEA'` 可以表示为 `ID='123_SEA'`，以实现复杂的唯一性约束。

### 将数据从 Neo4j 迁移到 Neptune 时的边缘方向优化
<a name="migration-data-edge-direction"></a>

当将节点、边缘或属性添加到 Neptune 时，将[以三种不同的方式自动为它们编制索引](feature-overview-storage-indexing.md)，并具有[可选的第四个索引](features-lab-mode.md#features-lab-mode-features-osgp-index)。由于 Neptune 构建和[使用索引](feature-overview-storage-indexing.md)的方式，遵循传出边缘的查询比使用传入边缘的查询效率更高。就 Neptune 的[图形数据存储模型](feature-overview-data-model.md)而言，这些是使用 SPOG 索引的基于主题的搜索。

如果在将数据模型和查询迁移到 Neptune 时，您发现最重要的查询依赖于遍历扇出程度很高的传入边缘，则可能需要考虑更改模型，以便这些遍历改为遵循传出边缘，尤其是在您无法指定要遍历哪些边缘标签时。为此，请反转相关边缘的方向并更新边缘标签，以反映此方向变化的语义。例如，您可能更改：

```
person_A — parent_of — person_B
   to:
person_B — child_of — person_A
```

要在[批量加载边缘 CSV 文件](bulk-load-tutorial-format.md)中进行此更改，只需交换 `~from` 和 `~to` 列标题，然后更新 `~label` 列的值即可。

作为反转边缘方向的替代方案，您可以启用[第四个 Neptune 索引，即 OSGP 索引](feature-overview-storage-indexing.md#feature-overview-storage-indexing-osgp)，这样可以更高效地遍历传入的边缘或基于对象的搜索。但是，启用该第四个索引将降低插入速率并需要更多的存储空间。

### 将数据从 Neo4j 迁移到 Neptune 时进行筛选优化
<a name="migration-data-filtering"></a>

Neptune 经过优化，当将属性筛选为最具选择性的可用属性时，效果最佳。当使用多个筛选条件时，会为每个筛选条件找到一组匹配的项目，然后计算出所有匹配集的重叠度。如果可能，将多个属性合并为一个属性，可以最大限度地减少索引查找次数并减少查询的延迟。

例如，此查询使用两个索引查找和一个联接：

```
MATCH (n) WHERE n.first_name='John' AND n.last_name='Doe' RETURN n
```

此查询使用单个索引查找来检索相同的信息：

```
MATCH (n) WHERE n.name='John Doe' RETURN n
```

### 
<a name="migration-data-types"></a>

Neptune 与 Neo4j 支持[不同的数据类型](bulk-load-tutorial-format-opencypher.md#bulk-load-tutorial-format-opencypher-data-types)。

**Neo4j 数据类型映射到 Neptune 支持的数据类型**
+ **逻辑**：`Boolean`

  在 Neptune 中将其映射到 `Bool` 或 `Boolean`。
+ **数值**：`Number`

  在 Neptune 中将其映射到以下 Neptune openCypher 类型中最窄的一个，这些类型可以支持相关数值属性的所有值：

  ```
    Byte
    Short
    Integer
    Long
    Float
    Double
  ```
+ **文本**：`String`

  在 Neptune 中将其映射到 `String`。
+ **时间点**：

  ```
    Date
    Time
    LocalTime
    DateTime
    LocalDateTime
  ```

  使用 Neptune 支持的以下 ISO-8601 格式之一，在 Neptune 中将其映射到 `Date` (UTC)：

  ```
    yyyy-MM-dd
    yyyy-MM-ddTHH:mm
    yyyy-MM-ddTHH:mm:ss
    yyyy-MM-ddTHH:mm:ssZ
  ```
+ **持续时间**：`Duration`

  如有必要，在 Neptune 中将其映射到日期算术的数值。
+ **空间**：`Point`

  在 Neptune 中将其映射为组件数值，然后每个数值都成为一个单独的属性，或者表示为字符串值以由客户端应用程序解释。请注意，Neptune 的使用 OpenSearch 的[全文搜索](full-text-search.md)集成允许您对地理位置属性编制索引。

### 将多值属性从 Neo4j 迁移到 Neptune
<a name="migration-data-cardinality"></a>

Neo4j 允许将[简单类型的同构列表](https://neo4j.com/docs/cypher-manual/current/values-and-types/)存储为节点和边缘的属性。这些列表可以包含重复的值。

但是，Neptune 只允许对顶点属性使用[集基数或单基数](access-graph-gremlin-differences.md#feature-gremlin-differences-vertex-property-cardinality)，而在属性图数据中允许对边缘属性使用单基数。因此，无法将包含重复值的 Neo4j 节点列表属性直接迁移到 Neptune 顶点属性，也无法将 Neo4j 关系列表属性直接迁移到 Neptune 边缘属性。

将具有重复值的 Neo4j 多值节点属性迁移到 Neptune 的一些可能策略如下：
+ 丢弃重复值并将多值 Neo4j 节点属性转换为集基数 Neptune 顶点属性。请注意，Neptune 集可能无法反映原始 Neo4j 多值属性中项目的顺序。
+ 将多值 Neo4j 节点属性转换为 Neptune 顶点字符串属性中 JSON 格式列表的字符串表示形式。
+ 将每个多值属性值提取到具有值属性的单独顶点中，然后使用标有属性名称的边缘将这些顶点连接到父顶点。

同样，将 Neo4j 多值关系属性迁移到 Neptune 的可能策略如下：
+ 将多值 Neo4j 关系属性转换为 JSON 格式列表的字符串表示形式，并将其存储为 Neptune 边缘字符串属性。
+ 将 Neo4j 关系重构为连接到中间顶点的传入和传出 Neptune 边缘。使用标有属性名称的边缘，将每个多值关系属性值提取到具有值属性的单独顶点中，并将这些顶点提取到该中间顶点。

请注意，尽管 openCypher 包含一个允许在字符串值中进行简单搜索的 `CONTAINS` 谓词，但 JSON 格式列表的字符串表示形式对于 openCypher 查询语言来说是不透明的。

## 迁移到 Neptune 时从 Neo4j 导出数据
<a name="migration-data-exporting"></a>

从 Neo4j 导出数据时，请使用 APOC 过程导出到 [CSV](https://neo4j.com/labs/apoc/4.1/export/csv/) 或 [GraphML](https://neo4j.com/labs/apoc/4.1/export/graphml/)。尽管可以导出到其它格式，但有一些[开源工具](https://github.com/awslabs/amazon-neptune-tools/tree/master/neo4j-to-neptune)可以将从 Neo4j 导出的 CSV 数据转换为 Neptune 批量加载格式，还有一些[开源工具](https://github.com/awslabs/amazon-neptune-tools/tree/master/graphml2csv)可以将从 Neo4j 导出的 GraphML 数据转换为 Neptune 批量加载格式。

也可以使用各种 APOC 过程将数据直接导出到 Amazon S3。默认情况下，导出到 Amazon S3 桶处于禁用状态，但可以使用 Neo4j APOC 文档的[导出到 Amazon S3](https://neo4j.com/labs/apoc/4.3/export/csv/#export-csv-s3-export) 中重点介绍的过程将其启用。

## 迁移到 Neptune 时从 Neo4j 导入数据
<a name="migration-data-importing"></a>

您可以使用 [Neptune 批量加载程序](bulk-load.md)或使用支持的查询语言（例如 [openCypher](access-graph-opencypher.md)）中的应用程序逻辑，将数据导入 Neptune。

Neptune 批量加载程序是导入大量数据的首选方法，因为如果您遵循[最佳实践](bulk-load-optimize.md)，它可以提供优化的导入性能。批量加载程序支持[两种不同的 CSV 格式](bulk-load-tutorial-format.md)，可以使用[导出数据](#migration-data-exporting)一节中提到的开源实用程序将从 Neo4j 导出的数据转换为这些格式。

还可以使用 openCypher 导入具有自定义逻辑的数据，用于解析、转换和导入。您可以通过 [HTTPS 端点](access-graph-opencypher-queries.md)（推荐使用）或使用 [bolt 驱动程序](access-graph-opencypher-bolt.md)提交 openCypher 查询。