

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 從 Neo4j 遷移到 Amazon Neptune
<a name="migrating-from-neo4j"></a>

Neo4j 和 Amazon Neptune 都是圖形資料庫，專為支援標記屬性圖資料模型的線上交易圖形工作負載而設計。這些相似性使得 Neptune 成為試圖遷移其目前 Neo4j 應用程式之客戶的共同選擇。不過，這些遷移不只是隨即轉移，因為兩個資料庫之間在語言和功能支援、操作特性、伺服器架構和儲存體功能方面存在差異。

此頁面會制定遷移程序，並提出將 Neo4j 圖形應用程式遷移到 Neptune 之前需要考慮的事項。這些考量通常適用於任何 Neo4j 圖形應用程式，無論是由 Community、Enterprise 還是 Aura 提供都一樣。雖然每個解決方案都是獨一無二的，並且可能需要額外的程序，但所有遷移都會遵循相同的一般模式。

以下各節中描述的每個步驟都包含簡化遷移程序的考量和建議。此外，還有[開放程式碼工具和描述該程序的部落格文章](migration-resources.md)，以及[功能相容性一節](migration-compatibility.md)，其中具有建議的架構選項。

**Topics**
+ [有關從 Neo4j 遷移到 Neptune 的一般資訊](migrating-from-neo4j-general.md)
+ [準備從 Neo4j 遷移到 Neptune](preparing-to-migrate-from-neo4j.md)
+ [從 Neo4j 遷移到 Neptune 時佈建基礎設施](migration-provisioning-infrastructure.md)
+ [資料從 Neo4j 遷移到 Neptune](migration-data-migration.md)
+ [應用程式從 Neo4j 遷移到 Neptune](migration-app-migration.md)
+ [Neptune 與 Neo4j 的相容性](migration-compatibility.md)
+ [重寫 Cypher 查詢以在 Neptune 上的 OpenCpher 中執行](migration-opencypher-rewrites.md)
+ [從 Neo4j 遷移到 Neptune 的資源](migration-resources.md)

# 有關從 Neo4j 遷移到 Neptune 的一般資訊
<a name="migrating-from-neo4j-general"></a>

透過 Neptune [對 OpenCypher 查詢語言的支援](feature-opencypher-compliance.md)，您可以將使用 Bolt 通訊協定或 HTTPS 的大多數 Neo4j 工作負載移至 Neptune。不過，OpenCypher 是一種開放程式碼規範，其中包含其他資料庫 (例如 Neo4j) 所支援功能的大部分但不是全部。

儘管在許多方面相容，Neptune 並不是 Neo4j 的直接替代品。Neptune 是一種全受管圖形資料庫服務，具有高可用性和高持久性等企業功能，在架構方面與 Neo4j 不同。Neptune 是以執行個體為基礎，具有單一主要寫入器執行個體和最多 15 個僅供讀取複本執行個體，可讓您水平擴展讀取容量。使用 [Neptune Serverless](neptune-serverless.md)，您可以自動向上擴展和縮減運算容量，取決於查詢磁碟區。這與 Neptune 儲存體無關，此儲存體會在您新增資料時自動擴展。

Neptune 支援開放原始碼 [openCypher 標準規格第 9 版](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf)。在 AWS，我們相信開放原始碼對每個人都有益，我們承諾將開放原始碼的價值帶給客戶，並將 AWS 的卓越營運帶給開放原始碼社群。

不過，在 Neo4j 上執行的許多應用程式也會使用不是開放原始碼且 Neptune 不支援的專屬功能。例如，Neptune 不支援 APOC 程序、某些 Cyphers 特定的子句和函數，以及 `Char`、`Date`、或 `Duration` 資料類型。Neptune 會自動將遺失的資料類型轉換為[支援的資料類型](bulk-load-tutorial-format-opencypher.md#bulk-load-tutorial-format-opencypher-data-types)。

除了 openCypher 之外，Neptune 還支援 [Apache TinkerPop Gremlin](https://tinkerpop.apache.org/docs/current/reference/#traversal) 查詢語言用於屬性圖 (以及支援 SPARQL 用於 RDF 資料)。Gremlin 可以在同一個屬性圖上與 OpenCypher 交互操作，並且在許多情況下，您可以使用 Gremlin 來提供 OpenCypher 未提供的功能。以下是兩種語言的快速比較：


|  | openCypher | Gremlin | 
| --- | --- | --- | 
| Style (樣式) | 宣告式 | 命令式 | 
| 語法 |  模式比對 <pre>Match p=(a)-[:route]->(d)<br />WHERE a.code='ANC'<br />RETURN p<br /></pre>  |  周遊型 <pre>g.V().has('code', 'ANC').<br />out('route').path().<br />by(elementMap())</pre>  | 
| 易於使用 | 受 SQL 啟發，非程式設計人員可讀取 | 更陡峭的學習曲線，類似於 Java 等程式設計語言 | 
| 彈性 | 低 | 高 | 
| 查詢支援 | 字串型查詢 | 用戶端程式庫支援的字串型查詢或內嵌程式碼 | 
| 用戶端 | HTTPS 和 Bolt | HTTPS 和 Websocket | 

一般來說，不需要變更資料模型，即可從 Neo4j 遷移到 Neptune，因為 Neo4j 和 Neptune 都支援標記的屬性圖 (LPG) 資料。不過，Neptune 有一些架構和資料模型差異，您可以利用這些差異來最佳化效能：例如：
+ Neptune ID 被視為頭等公民。
+ Neptune 會使用 [AWS Identity and Access Management (IAM) 政策](iam-auth.md)，以靈活且精細的方式保護對圖形資料的存取。
+ Neptune 會提供幾種方式，來[使用 Jupyter 筆記本](graph-notebooks.md)以執行查詢和[視覺化結果](notebooks-visualization.md)。Neptune 也會使用[第三方視覺化工具](visualization-tools.md)。
+ > 雖然 Neptune 沒有 Neo4j 圖形資料科學 (GDS) 程式庫的直接替代品，但是 Neptune 如今會透過各種解決方案支援圖形分析。例如，數個[範例筆記本](https://github.com/aws/graph-notebook/tree/main/src/graph_notebook/notebooks/01-Neptune-Database/03-Sample-Applications/06-Data-Science-Samples)示範如何在 Python 環境中利用 Neptune [與 AWS Pandas SDK 的整合](https://github.com/amazon-archives/fully-automated-neo4j-to-neptune)，對圖形資料執行分析。

如果您有任何問題，請聯絡 AWS 支援或與您的 AWS 客戶團隊互動。我們會使用您的意見回饋，來排定符合您需求之新功能的優先順序。

# 準備從 Neo4j 遷移到 Neptune
<a name="preparing-to-migrate-from-neo4j"></a>

 從 Neo4j 圖形資料庫遷移至 Neptune 圖形資料庫服務的方式有兩種：重新建構或重構/重新架構。重構方法涉及修改現有的資料模型和應用程式架構，以充分利用 Neptune 的功能，而重構方法著重於在 Neptune 中尋找同等元件，以建置相當的實作。實際上，通常會使用這些策略的組合，因為遷移程序涉及平衡目標 Neptune 架構與現有 Neo4j 實作的限制和需求。無論方法為何，關鍵是從應用程式的使用案例向後工作，以設計最符合您需求的資料模型、查詢和整體架構。

## 遷移的方法
<a name="migration-approaches"></a>

將 Neo4j 應用程式遷移到 Neptune 時，我們建議您使用以下兩種策略之一：平台轉換或重構/重新架構。如需有關遷移策略的詳細資訊，請參閱[將應用程式遷移至雲端的 6 個策略](https://aws.amazon.com/blogs/enterprise-strategy/6-strategies-for-migrating-applications-to-the-cloud/)，這是 Stephen Orban 所撰寫的部落格文章。

「平台轉換方法」**有時稱為「捨棄再購買」(lift-tinker-and-shift)**，其中涉及以下步驟：
+ 識別您的應用程式想要滿足的使用案例。
+ 修改現有的圖形資料模型和應用程式架構，以使用 Neptune 的功能充分處理這些工作負載需求。
+ 決定如何將來源應用程式的資料、查詢和其他部分遷移至目標模型和架構。

如果這是一個全新的專案，這種回溯運作方法可讓您將應用程式遷移到您可能設計的 Neptune 解決方案。

相比之下，「重構方法」**涉及：
+ 識別現有實作的元件，包括基礎設施、資料、查詢和應用程式功能。
+ 在 Neptune 中尋找可用來建置類似實作的等效項目。

這種向前運作方法試圖將一個實作交換為另一個實作。

在實務中，您可能會採用這兩種方法的混合。您可以從使用案例開始，設計目標 Neptune 架構，但然後轉至現有的 Neo4j 實作，來識別您必須維護的限制條件和不變量。例如，您可能必須繼續與其他外部系統整合，或繼續為圖形應用程式的消費者提供特定的 API。使用此資訊，您可以判斷已存在哪些資料要移至目標模型，以及哪些資料必須在其他位置取得。

在其他時候，您可能從分析 Neo4j 實作的特定部分開始，作為最佳資訊來源，取得應用程式打算執行之工作的相關資訊。現有應用程式中的這種考古方式可以協助定義一個使用案例，然後您可以使用 Neptune 的功能針對其進行設計。

無論您是使用 Neptune 建置新的應用程式還是從 Neo4j 遷移現有的應用程式，我們建議您透過使用案例的回溯運作來設計資料模型、一組查詢，以及處理您商務需求的應用程式架構。

# Neptune 與 Neo4j 之間的架構差異
<a name="migration-architectural-differences"></a>

當客戶第一次考慮將應用程式從 Neo4j 遷移到 Neptune 時，通常很容易根據執行個體大小執行類似的比較。不過，Neo4j 和 Neptune 的架構有著根本上的差異。Neo4j 基於一體化方法，其中資料載入、資料 ETL、應用程式查詢、資料儲存以及管理操作都在同一組運算資源 (例如 EC2 執行個體) 中進行。

相比之下，Neptune 是以 OLTP 為中心的圖形資料庫，其中架構會分隔責任且資源會被分開，以便它們可以動態和獨立擴展。

從 Neo4j 遷移到 Neptune 時，請確定應用程式的資料持久性、可用性和可擴展性需求。Neptune 的叢集架構可簡化需要高持久性、可用性和可擴展性之應用程式的設計。了解 Neptune 的叢集架構後，您就可以設計 Neptune 叢集拓撲來滿足這些需求。

## Neo4j 的叢集架構
<a name="migration-neo4j-cluster-architecture"></a>

許多生產應用程式會使用 Neo4j 的[因果叢集](https://neo4j.com/docs/operations-manual/current/clustering/introduction/)來提供資料持久性、高可用性和可擴展性。Neo4j 的叢集架構會使用核心伺服器和僅供讀取複本執行個體：
+ 核心伺服器透過使用 Rraft 通訊協定複寫資料，提供資料持久性和容錯能力。
+ 僅供讀取複本會使用交易日誌傳送，以非同步方式複寫高讀取輸送量工作負載的資料。

叢集中的每個執行個體 (不論是核心伺服器還是僅供讀取複本) 都包含圖形資料的完整副本。

## Neptune 的叢集架構
<a name="migration-neptune-cluster-architecture"></a>

[Neptune 叢集](feature-overview-db-clusters.md)是由一個主要寫入器執行個體和最多 15 個僅供讀取複本執行個體組成。叢集中的所有執行個體共用與執行個體分開的相同基礎分散式儲存服務。
+ 主要寫入器執行個體會協調資料庫的所有寫入操作，並可垂直擴展，以針對不同的寫入工作負載提供彈性支援。它還支援讀取操作。
+ 僅供讀取複本執行個體支援基礎儲存磁碟區的讀取操作，並可讓您水平擴展以支援高讀取工作負載。它們也會做為主要執行個體的容錯移轉目標，以提供高可用性。
**注意**  
對於繁重的寫入工作負載，最好將僅供讀取複本執行個體擴展至與寫入器執行個體相同的大小，以確保讀取器可以與資料變更保持一致。
+ 基礎儲存磁碟區會在資料庫中的資料增加時自動擴展儲存體容量，儲存體最多可為 128 TiB。

執行個體大小是動態且獨立的。每個執行個體都可以在叢集執行時調整大小，而且可以在叢集執行時新增或移除僅供讀取複本。

[Neptune Serverless](neptune-serverless.md) 功能可以隨著需求增加和降低自動擴展您的運算容量。這不僅可以降低您的管理負荷，還可以讓您設定資料庫來處理需求中的大量激增，而不會降低效能或要求您過度佈建。

您最多可以停止 Neptune 叢集 7 天。

Neptune 還支援[自動擴展](manage-console-autoscaling.md)，以根據工作負載自動調整讀取器執行個體大小。

使用 Neptune 的[全球資料庫功能](neptune-global-database.md)，您最多可在 5 個其他區域鏡像叢集。

Neptune 也會[特意設計為具備容錯能力](backup-restore-overview-fault-tolerance.md)：
+ 將資料儲存提供給叢集中所有執行個體的叢集磁碟區跨越單一 AWS 區域中的多個可用區域 (AZ)。每個可用區域都包含叢集資料的完整副本。
+ 如果主要執行個體無法使用，Neptune 會自動容錯移轉到現有的僅供讀取複本，資料不會遺失，通常在 30 秒內完成。如果叢集中沒有現有的僅供讀取複本，Neptune 會自動佈建新的主要執行個體 - 同樣，不會遺失資料。

這一切意味著，從 Neo4j 因果叢集遷移到 Neptune 時，您不必明確地架構叢集拓撲，以實現高資料持久性和高可用性。這使您只需透過幾種方式便可針對預期的讀取和寫入工作負載，以及任何增加的可用性需求調整叢集大小：
+ 若要擴展讀取操作，請[新增僅供讀取複本執行個體](feature-overview-db-clusters.md#feature-overview-read-replicas)或啟用 [Neptune Serverless](neptune-serverless.md) 功能。
+ 若要改善可用性，請將叢集中的主要執行個體和僅供讀取複本分佈在數個可用區域 (AZ) 上。
+ 若要縮短任何容錯移轉時間，請至少佈建一個僅供讀取複本執行個體，做為主要執行個體的容錯移轉目標。您可以[指派每個複本的優先順序](manage-console-add-replicas.md)，確定僅供讀取複本執行個體在失敗之後提升為主要執行個體的順序。最佳實務是確保容錯移轉目標具有能夠處理應用程式寫入工作負載的執行個體類別 (如果提升為主要執行個體的話)。

# Neptune 與 Neo4j 之間的資料儲存差異
<a name="migration-storage-differences"></a>

Neptune 會使用以原生四元組模型為基礎的[圖形資料模型](feature-overview-data-model.md)。將資料遷移至 Neptune 時，資料模型和儲存層的架構中有幾個差異，您應該注意這些差異，以充分利用 Neptune 提供的分散式和可擴展共用儲存體：
+ Neptune 不會使用任何明確定義的結構描述或限制條件。它可讓您動態新增節點，邊緣和屬性，而無需提前定義結構描述。Neptune 不會限制所儲存資料的值和類型，但 [Neptune 限制](limits.md#limits-properties)中提及的除外。作為 Neptune 儲存體架構的一部分，資料也會以處理許多最常見存取模式的方式[自動編製索引](feature-overview-storage-indexing.md)。這種儲存體架構移除了建立和管理資料庫結構描述和索引最佳化的操作負荷。
+ Neptune 提供唯一的分散式和共用儲存體架構，此架構會隨著資料庫的儲存體需求成長自動以 10 GB 區塊擴展，最高可達 128 TiB。此儲存層可靠、耐用且容錯，資料複製 6 次，其中 3 個可用區域各複製 2 次，。根據預設，它為所有 Neptune 叢集提供高可用性和容錯資料儲存層。Neptune 的儲存體架構可降低成本，並免除佈建或過度佈建儲存體以處理未來資料成長的需求。

在將您的資料遷移到 Neptune 之前，最好先熟悉 Neptune 的[屬性圖資料模型](feature-overview-storage-indexing.md#feature-overview-storage-indexing-gremlin)和[交易語義](transactions.md)。

# Neptune 與 Neo4j 之間的操作差異
<a name="migration-operational-differences"></a>

Neptune 是一個全受管服務，可以自動執行您在使用內部部署或自我管理的資料庫 (例如 Neo4j 企業版或社群版) 時必須執行的許多正常操作任務：
+ **[自動備份](backup-restore.md#backup-restore-overview-backups)** – Neptune 會自動備份您的叢集磁碟區，並在您指定的保留期 (從 1 到 35 天) 保留備份。這些備份具有連續性和增量性，因此，您可以快速還原到保留期內的任何時間點。寫入備份資料時不會影響資料庫服務的效能或中斷服務。
+ **[手動快照](backup-restore.md)** – Neptune 可讓您建立資料庫叢集的儲存磁碟區快照，來備份整個資料庫叢集。然後，這種快照可以用來還原資料庫、製作其副本，以及跨帳戶共用。
+ **[複製](manage-console-cloning.md)** – Neptune 支援複製功能，此功能可讓您快速建立具成本效益的資料庫複製。複製會使用寫入時複製通訊協定，以在建立它們之後只需要最少的額外空間。資料庫複製是試用新 Neptune 功能或升級的有效方法，而不會中斷原始叢集。
+ **[監控](monitoring.md)** – Neptune 提供各種方法來監控叢集的效能和使用情況，包括：
  + 執行個體
  + 與 Amazon CloudWatch 和 整合 AWS CloudTrail
  + 稽核日誌功能
  + 事件通知
  + 標記
+ **[安全性](security.md)** – Neptune 預設會提供安全環境。叢集位於私有 VPC 內，此 VPC 會提供與其他資源的網路隔離。所有流量都會透過 SSL 加密，而所有資料都會使用 進行靜態加密 AWS KMS。

  此外，Neptune 與 AWS Identity and Access Management (IAM) 整合以提供[身分驗證](iam-auth.md)。透過指定 [IAM 條件金鑰](iam-condition-keys.md)，您可以使用 IAM 政策，對[資料動作](iam-data-access-policies.md)提供更精細的存取控制。

## Neptune 與 Neo4j 之間的工具和整合差異
<a name="migration-tooling-differences"></a>

Neptune 具有與 Neo4j 不同的整合和工具架構，這可能會影響應用程式的架構。Neptune 會使用叢集的運算資源來處理查詢，但會針對全文搜尋 （使用 OpenSearch)、ETL （使用 Glue) 等功能，利用其他best-in-class AWS 服務。如需這些整合的完整清單，請參閱 [Neptune 整合](integrations.md)。

# 從 Neo4j 遷移到 Neptune 時佈建基礎設施
<a name="migration-provisioning-infrastructure"></a>

Amazon Neptune 叢集是為了在三個維度中進行擴展而建置的：儲存體、寫入容量和讀取容量。以下各節討論遷移時要考慮的特定選項。

## 佈建儲存體
<a name="migration-provisioning-storage"></a>

任何 Neptune 叢集的儲存體都是自動佈建的，您的部分沒有任何管理負荷。隨著叢集的儲存體需求增加，它會以 10 GB 區塊動態調整大小。因此，不需要估計和佈建或過度佈建儲存體來處理未來的資料成長。

## 佈建寫入容量
<a name="migration-provisioning-write-capacity"></a>

Neptune 會提供單一寫入器執行個體，其可以垂直擴展為 [Neptune 定價頁面](https://aws.amazon.com/neptune/pricing/)上提供的任何執行個體大小。讀取資料和寫入資料至寫入器執行個體時，所有交易都符合 ACID 規範，而資料隔離如 [Neptune 中的交易隔離層級](transactions-neptune.md) 中所定義。

為寫入器執行個體選擇最佳大小需要執行載入測試，以確定工作負載的最佳執行個體大小。您可以[修改資料庫執行個體類別](manage-console-instances-modify.md)，隨時調整 Neptune 內的任何執行個體大小。您可以根據並行性和平均查詢延遲來估計起始執行個體大小，如下面 [佈建叢集時估計最佳的執行個體大小](#migration-provisioning-instance-sizing) 所述。

## 佈建讀取容量
<a name="migration-provisioning-read-capacity"></a>

建置 Neptune 是為了水平擴展 （方法是在叢集內新增最多 15 個僅供讀取複本，或在 [Neptune 全球資料庫](neptune-global-database.md)中新增更多的僅供讀取複本) 僅供讀取複本執行個體，並將其垂直擴展至 [Neptune 定價頁面](https://aws.amazon.com/neptune/pricing/)上提供的任何執行個體大小。所有 Neptune 僅供讀取複本執行個體都會使用相同的基礎儲存磁碟區，從而以最小的延遲啟用資料的透明複寫。

除了啟用 Neptune 叢集內讀取請求的水平擴展之外，僅供讀取複本也可做為寫入器執行個體的容錯移轉目標，以啟用高可用性。如需如何確定叢集中僅供讀取複本的適當數量和放置位置的建議，請參閱 [Amazon Neptune 基本操作準則](best-practices-general-basic.md)。

對於無法預測其連線能力和工作負載的應用程式，Neptune 也支援[自動擴展功能](manage-console-autoscaling.md)，其可根據您指定的準則自動調整 Neptune 複本的數量。

若要確定僅供讀取複本執行個體的最佳大小和數量，需要執行載入測試以確定其必須支援的讀取工作負載特性。您可以[修改資料庫執行個體類別](manage-console-instances-modify.md)，隨時調整 Neptune 內的任何執行個體大小。您可以根據並行性和平均查詢延遲來估計起始執行個體大小，如[下節](#migration-provisioning-instance-sizing)所述。

## 使用 Neptune Serverless 視需要自動擴展讀取器和寫入器執行個體
<a name="migration-provisioning-serverless"></a>

雖然能夠估計預期工作負載所需的運算容量通常很有幫助，但您可以設定 [Neptune Serverless](neptune-serverless.md) 功能，以自動擴增和縮減讀取和寫入容量。這可協助您滿足尖峰需求，同時也會在需求減少時自動縮減回來。

## 佈建叢集時估計最佳的執行個體大小
<a name="migration-provisioning-instance-sizing"></a>

估計最佳執行個體大小需要知道 Neptune 中的平均查詢延遲、工作負載執行時間，以及正在處理的並行查詢數目。執行個體大小的粗略估計值可以計算為平均查詢延遲乘以並行查詢數目。這會提供您處理工作負載所需之並行執行緒的平均數目。

Neptune 執行個體中的每個 vCPU 都可以支援兩個並行查詢執行緒，因此將執行緒除以 2 可提供所需的 vCPU 數目，然後這些 vCPU 可與 [Neptune 定價頁面](https://aws.amazon.com/neptune/pricing/)上的適當執行個體大小相互關聯。例如：

```
Average Query Latency:         30ms (0.03s)
Number of concurrent queries:  1000/second

Number of threads needed:      0.03 x 1000 = 30 threads
Number of vCPUs needed:        30 / 2 = 15 vCPUs
```

將此數目與執行個體中的 vCPU 數目相互關聯，我們發現我們得到了一個粗略的估計，即 `r5.4xlarge` 將是要為此工作負載嘗試的建議執行個體。這個估計是粗略的，只是為了提供執行個體大小選擇的初始指引。任何應用程式都應該進行調整適當大小的練習，以確定適合工作負載的執行個體數目和類型。

記憶體需求以及處理需求也應納入考慮。當查詢正在存取的資料在主記憶體緩衝集區快取中可用時，Neptune 的效能最佳。佈建足夠的記憶體也可大幅降低 I/O 成本。

您可以在 [調整 Neptune 資料庫叢集中資料庫執行個體的大小](feature-overview-db-clusters.md#feature-overview-sizing-instances) 頁面上找到有關調整 Neptune 叢集中執行個體大小的其他詳細資訊和指引。

# 資料從 Neo4j 遷移到 Neptune
<a name="migration-data-migration"></a>

從 Neo4j 遷移到 Amazon Neptune 時，遷移資料是過程中的主要步驟。有多種方法遷移資料。正確的方法取決於應用程式的需求、資料大小和所需的遷移類型。不過，其中許多遷移都需要評估相同的考量，其中幾個會在下面反白顯示。

**注意**  
請參閱 [AWS 資料庫部落格](https://aws.amazon.com/blogs/?awsf.blog-master-category=category%23database)中的[使用全自動化公用程式將 Neo4j 圖形資料庫遷移至 Neptune](https://aws.amazon.com/blogs/database/migrating-a-neo4j-graph-database-to-amazon-neptune-with-a-fully-automated-utility/)，以取得如何執行離線資料遷移之範例的完整逐步解說。

## 評估從 Neo4j 到 Neptune 的資料遷移
<a name="migration-data-assessment"></a>

評估任何資料遷移時的第一步是確定如何遷移資料。這些選項取決於要遷移之應用程式的架構、資料大小，以及遷移期間的可用性需求。通常，遷移往往分為兩種類別之一：線上或離線。

離線遷移往往是最簡容易完成的，因為應用程式在遷移期間不接受讀取或寫入流量。在應用程式停止接受流量之後，可以匯出、最佳化、匯入資料，並在重新啟用應用程式之前測試應用程式。

線上遷移較為複雜，因為在遷移資料時，應用程式仍然需要接受讀取和寫入流量。每個線上遷移的確切需求可能會有所不同，但一般架構通常會與下列架構類似：
+ 資料庫的持續變更摘要需要在 Neo4j 中啟用，方法是設定 [Neo4j 串流作為 Kafka 叢集的來源](https://neo4j.com/labs/kafka/4.0/producer/)。
+ 一旦完成此操作，就可以遵循 [遷移到 Neptune 時從 Neo4j 匯出資料](#migration-data-exporting) 中的指示，以及稍後與 Kafka 主題相互關聯時提到的時間取得執行中系統的匯出。
+ 然後，匯出的資料會遵循 [遷移到 Neptune 時從 Neo4j 匯入資料](#migration-data-importing) 中的指示匯入至 Neptune。
+ 來自 Kafka 串流的變更資料接著可以複製到 Neptune 叢集，方法是使用與[從 Amazon Kinesis Data Streams 寫入至 Amazon Neptune](https://github.com/aws-samples/amazon-neptune-samples/tree/master/gremlin/stream-2-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，其中它們是以字串表示，而不是數值。

不過，在某些情況下，您可能想要提升頂點屬性以成為頂點 ID。就像使用編製索引的屬性查閱節點是在 Neo4j 中尋找節點的最快方法一樣，按 ID 查閱頂點是在 Neptune 中尋找頂點的最快方法。因此，如果您可以識別包含唯一值的適當頂點屬性，則應考慮在大量載入 CSV 檔案中以指定的屬性值取代頂點 \$1id。如果這樣做，您還必須在 CSV 文件中重寫任何對應的 \$1from 和 \$1to 邊緣值。

### 將資料從 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 邊緣。將每個多值關係屬性值擷取至具有值屬性的個別頂點，然後使用以屬性名稱標記的邊緣將這些頂點連線到此中繼頂點。

請注意，JSON 格式清單的字串表示法對 OpenCypher 查詢語言來說是不透明的，雖然 OpenCypher 包含允許在字串值內進行簡單搜尋的 `CONTAINS` 述詞。

## 遷移到 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 查詢。

# 應用程式從 Neo4j 遷移到 Neptune
<a name="migration-app-migration"></a>

在您已將資料從 Neo4j 遷移到 Neptune 之後，下一步是遷移應用程式本身。與資料一樣，根據您使用的工具、需求、架構差異等，有多種遷移應用程式的方法。下面概述了您通常需要在此過程中考慮的事項。

## 從 Neo4j 移到 Neptune 時遷移連線
<a name="migration-app-connections"></a>

如果您目前未使用 Bolt 驅動程式，或想要使用替代驅動程式，您可以連線至 [HTTPS 端點](access-graph-opencypher-queries.md)，該端點可提供對所傳回資料的完整存取權。

如果您確實具有使用 [Bolt 通訊協定](access-graph-opencypher-bolt.md)的應用程式，則可以將這些連線遷移到 Neptune，並讓您的應用程式可以使用與您在 Neo4j 中使用的同一驅動程式進行連線。若要連線到 Neptune，您可能需要對應用程式進行下列一或多個變更：
+ 必須更新 URL 和連接埠，才能使用叢集端點和叢集連接埠 (預設值為 8182)。
+ Neptune 會要求所有連線都使用 SSL，因此您需要為每個連線指定加密。
+ Neptune 透過指派 [IAM 政策和角色](iam-auth.md)來管理身分驗證。IAM 政策和角色在應用程式內提供極為靈活的使用者管理層級，因此在設定叢集之前，務必先閱讀並了解 [IAM 概觀](iam-auth.md)中的資訊。
+ Bolt 連線在 Neptune 中的行為與在 Neo4j 中的行為會在幾個方面有所不同，如 [Neptune 中的 Bolt 連線行為](access-graph-opencypher-bolt.md#access-graph-opencypher-bolt-connections) 中所述。
+ 您可以在 [使用 openCypher 和 Bolt 的 Neptune 最佳實務](best-practices-opencypher.md) 中找到更多的資訊和建議。

在 [使用 Bolt 通訊協定，對 Neptune 進行 openCypher 查詢](access-graph-opencypher-bolt.md) 中，有一些常用語言 (例如 Java、Python、.NET 和 NodeJS) 的程式碼範例，以及連線案例 (例如使用 IAM 身分驗證) 的程式碼範例。

## 從 Neo4j 移到 Neptune 時將查詢路由到叢集執行個體
<a name="migration-app-routing"></a>

Neo4j 的用戶端應用程式會使用[路由驅動程式](https://neo4j.com/docs/driver-manual/1.7/client-applications/#routing_drivers_bolt_routing)，並指定[存取模式](https://neo4j.com/docs/driver-manual/1.7/sessions-transactions/#driver-transactions-access-mode)，以將讀取和寫入請求路由至因果叢集中適當的伺服器。

將用戶端應用程式遷移至 Neptune 時，請使用 [Neptune 端點](feature-overview-endpoints.md)將查詢有效率地路由至叢集中適當的執行個體：
+ Neptune 的所有連線都應在 URL 中使用 `bolt://`，而不是 `bolt+routing://` 或 `neo4j://`。
+ 叢集端點會連線至叢集中目前的主要執行個體。使用叢集端點將寫入請求路由至主要執行個體。
+ 讀取器端點會將[連線分發](best-practices-general-basic.md#best-practices-general-loadbalance)到叢集中的僅供讀取複本執行個體。如果您具有的單一執行個體叢集沒有僅供讀取複本執行個體，則讀取器端點會連線到支援寫入操作的主要執行個體。如果叢集確實包含一或多個僅供讀取複本執行個體，則將寫入請求傳送至讀取器端點會產生例外狀況。
+ 叢集中的每個執行個體也可以具有自己的執行個體端點。如果您的用戶端應用程式需要將請求傳送至叢集中的特定執行個體，請使用執行個體端點。

如需詳細資訊，請參閱[Neptune 端點考量](feature-overview-endpoints.md#feature-overview-endpoint-considerations)。

## Neptune 中的資料一致性
<a name="migration-app-consistency"></a>

使用 Neo4j 因果叢集時，僅供讀取複本最終會與核心伺服器一致，但用戶端應用程式可以使用[因果鏈](https://neo4j.com/docs/driver-manual/1.7/sessions-transactions/#driver-transactions-causal-chaining)來確保因果一致性。因果鏈需要在交易之間傳遞書籤，這允許用戶端應用程式寫入核心伺服器，然後從僅供讀取複本讀取自己的寫入。

在 Neptune 中，僅供讀取複本執行個體最終會與寫入器一致，複本延遲通常少於 100 毫秒。不過，在複寫變更之前，複本執行個體上看不到對現有邊緣和頂點的更新，以及新增的邊緣和頂點。因此，如果您的應用程式需要透過讀取每個寫入以在 Neptune 上立即保持一致性，請使用叢集端點進行先讀後寫操作。這是使用叢集端點進行讀取操作的唯一時機。在所有其他情況下，請使用讀取器端點進行讀取。

## 將查詢從 Neo4j 遷移到 Neptune
<a name="migration-app-queries"></a>

儘管 Neptune [對 OpenCypher 的支援](https://aws.amazon.com/blogs/database/announcing-the-general-availability-of-opencypher-support-for-amazon-neptune/)大幅地減少了從 Neo4j 遷移查詢所需的工作量，但仍有一些在遷移時要評估的差異：
+ 如上面 [資料模型最佳化](migration-data-migration.md#migration-data-model-optimization) 中所討論，您可能需要對資料模型進行修改，以便為 Neptune 建立最佳化的圖形資料模型，因而需要對您的查詢和測試進行變更。
+ Neo4j 提供了各種 Cypher 特定的語言延伸模組，這些延伸模組不包括在由 Neptune 實作的 OpenCypher 規格中。根據使用案例和使用的功能，OpenCypher 語言內可能有因應措施，或使用 Gremlin 語言，或透過其他機制 (如 [重寫 Cypher 查詢以在 Neptune 上的 OpenCpher 中執行](migration-opencypher-rewrites.md) 中所述)。
+ 應用程式通常會使用其他中介軟體元件與資料庫互動，而不是 Bolt 驅動程式本身。請檢查 [Neptune 與 Neo4j 的相容性](migration-compatibility.md) 以查看是否支援您正在使用的工具或中介軟體。
+ 在容錯移轉的情況下，Bolt 驅動程式可能會繼續連線到先前的寫入器或讀取器執行個體，因為提供給連線的叢集端點已解析為 IP 地址。您應用程式中的適當錯誤處理應該處理這個問題，如 [在容錯移轉之後建立新連線](best-practices-opencypher.md#best-practices-opencypher-renew-connection) 中所述。
+ 交易由於無法解決的衝突或鎖定等待逾時而取消時，Neptune 會以 `ConcurrentModificationException` 回應。如需詳細資訊，請參閱[引擎錯誤代碼](errors-engine-codes.md)。根據最佳實務，用戶端應一律截獲和處理這些例外狀況。

  當多個執行緒或多個應用程式同時寫入系統時，偶爾會發生 `ConcurrentModificationException`。由於[交易隔離層級](transactions-neptune.md#transactions-neptune-mutation)，因此這些衝突有時可能是不可避免的。
+ Neptune 支援在相同的資料上執行 Gremlin 和 OpenCypher 查詢。這表示在某些情況下，您可能需要考慮使用查詢功能更強大的 Gemlin，來執行查詢的某些功能。

如上面 [佈建基礎設施](migration-provisioning-infrastructure.md) 所討論，每個應用程式都應該經過調整適當大小的練習，以確保執行個體數量、執行個體大小和叢集拓撲都針對應用程式的特定工作負載進行最佳化。

這裡針對遷移應用程式討論的考量是最常見的，但這不是一個詳盡的清單。每個應用程式都是唯一的。如果您有其他問題，請聯絡 AWS 支援或與您的客戶團隊互動。

## 遷移 Neo4j 特定功能和工具
<a name="migration-app-neo4j-specific"></a>

Neo4j 具有各種自訂功能和附加元件，其中具有您的應用程式可能依賴的功能。評估遷移此功能的需求時，通常有助於調查內部是否有更好的方法來 AWS 實現相同的目標。考慮到 [ Neo4j 和 Neptune 之間的架構差異](migration-architectural-differences.md)，您通常可以找到利用其他 AWS 服務或[整合](integrations.md)的有效替代方案。

如需 Neo4J 特定功能和所建議因應措施的清單，請參閱 [Neptune 與 Neo4j 的相容性](migration-compatibility.md)。

# Neptune 與 Neo4j 的相容性
<a name="migration-compatibility"></a>

Neo4j 具有一體化架構方法，其中資料載入、資料 ETL、應用程式查詢、資料儲存以及管理操作都在同一組運算資源 (例如 EC2 執行個體) 中進行。Amazon Neptune 是以 OLTP 為中心的開放規格圖形資料庫，其中架構會分隔操作並分離資源，以便它們可以動態擴展。

Neo4j 中有各種功能和工具，包括第三方工具，這些工具不是 OpenCypher 規格的一部分、與 OpenCypher 不相容，或與 Neptune 的 OpenCypher 實作不相容。下方列出一些最常見的功能和工具。

## Neptune 中不存在的 NEO4J 特定功能
<a name="migration-compatibility-features"></a>
+ **`LOAD CSV`** – Neptune 具有與 Neo4j 不同的架構方法來載入資料。為了允許更好的擴展和成本最佳化，Neptune 實作了涉及資源的分隔，並建議您使用其中一個 [AWS 服務整合](integrations.md) (例如 AWS Glue )，來執行必要的 ETL 程序，以 [Neptune 大量載入器](bulk-load.md)所支援的[格式](bulk-load-tutorial-format.md)準備資料。

  另一個選項是使用在 Amazon EC2 執行個體、Lambda 函數、Amazon Elastic Container Service、 AWS Batch jobs 等 AWS 運算資源上執行的應用程式程式碼來執行相同的操作。此程式碼可以使用 Neptune 的 [HTTPS 端點](access-graph-opencypher-queries.md)或 [Bolt 端點](access-graph-opencypher-bolt.md)。
+ **精細的存取控制** – Neptune 支援[使用 IAM 條件金鑰](iam-data-access-policies.md)，對資料存取動作進行精細的存取控制。可以在應用程式層實現其他精細的存取控制。
+ **Neo4j Fabric** – Neptune 確實支援使用 SPARQL [`SERVICE`](sparql-service.md) 關鍵字，對 RDF 工作負載進行跨資料庫的查詢聯合。由於目前沒有針對屬性圖工作負載的查詢聯合開放標準或規格，因此需要在應用程式層實作該功能。
+ **角色型存取控制 (RBAC)** – Neptune 透過指派 [IAM 政策和角色](iam-auth.md)來管理身分驗證。IAM 政策和角色在應用程式內提供極為靈活的使用者管理層級，因此值得在設定叢集之前，先閱讀並了解 [IAM 概觀](iam-auth.md)中的資訊。

  
+ **書籤** – Neptune 叢集由單一寫入器執行個體和最多 15 個僅供讀取複本執行個體組成。寫入至寫入器執行個體的資料符合 ACID 規範，並會在後續讀取時提供強大的一致性保證。僅供讀取複本會使用與寫入器執行個體相同的儲存磁碟區，並且最終保持一致，通常在寫入資料後不到 100 毫秒內。如果您的使用案例立即需要保證新寫入的讀取一致性，則這些讀取應導向至叢集端點，而不是讀取器端點。
+ **APOC 程序** – 由於 APOC 程序不包含在 OpenCypher 規格中，因此 Neptune 不提供外部程序的直接支援。相反地，Neptune 依賴[與其他 AWS 服務的整合](integrations.md)，以可擴展、安全且強大的方式實現類似的最終使用者功能。有時候 APOC 程序可以在 OpenCypher 或 Gremlin 中重寫，有些與 Neptune 應用程式無關。

  一般而言，APOC 程序分為以下類別：
  + **[匯入](https://neo4j.com/labs/apoc/4.2/import/)** – Neptune 支援使用查詢語言、Neptune [大量載入器](bulk-load.md)或作為 [AWS Database Migration Service](dms-neptune.md) 的目標，搭配各種格式匯入資料。可以使用 AWS Glue 和[https://github.com/awslabs/amazon-neptune-tools/tree/master/neptune-python-utils](https://github.com/awslabs/amazon-neptune-tools/tree/master/neptune-python-utils)開放原始碼套件執行資料上的 ETL 操作。
  + **[匯出](https://neo4j.com/labs/apoc/4.2/export/)** – Neptune 支援使用 [`neptune-export`](neptune-data-export.md) 公用程式匯出資料，該公用程式支援各種常見的匯出格式和方法。
  + **[資料庫整合](https://neo4j.com/labs/apoc/4.2/database-integration/)** – Neptune 支援使用 ETL 工具整合其他資料庫，例如 AWS Glue 或遷移工具，例如 [AWS Database Migration Service](dms-neptune.md)。
  + **[圖形更新](https://neo4j.com/labs/apoc/4.2/graph-updates/)** – Neptune 透過對 OpenCypher 和 Gremlin 查詢語言的支援，支援一組豐富的功能更新屬性圖資料。如需重寫常用程序的範例，請參閱 [Cypher 重寫](migration-opencypher-rewrites.md)。
  + **[資料結構](https://neo4j.com/labs/apoc/4.2/data-structures/)** – Neptune 透過對 OpenCypher 和 Gremlin 查詢語言的支援，支援一組豐富的功能更新屬性圖資料。如需重寫常用程序的範例，請參閱 [Cypher 重寫](migration-opencypher-rewrites.md)。
  + **[暫時 (日期時間)](https://neo4j.com/labs/apoc/4.2/temporal/)** – Neptune 透過對 OpenCypher 和 Gremlin 查詢語言的支援，支援一組豐富的功能更新屬性圖資料。如需重寫常用程序的範例，請參閱 [Cypher 重寫](migration-opencypher-rewrites.md)。
  + **[數學](https://neo4j.com/labs/apoc/4.2/mathematical/)** – Neptune 透過對 OpenCypher 和 Gremlin 查詢語言的支援，支援一組豐富的功能更新屬性圖資料。如需重寫常用程序的範例，請參閱 [Cypher 重寫](migration-opencypher-rewrites.md)。
  + **[進階圖形查詢](https://neo4j.com/labs/apoc/4.2/graph-querying/)** – Neptune 透過對 OpenCypher 和 Gremlin 查詢語言的支援，支援一組豐富的功能更新屬性圖資料。如需重寫常用程序的範例，請參閱 [Cypher 重寫](migration-opencypher-rewrites.md)。
  + **[比較圖形](https://neo4j.com/labs/apoc/4.2/comparing-graphs/)** – Neptune 透過對 OpenCypher 和 Gremlin 查詢語言的支援，支援一組豐富的功能更新屬性圖資料。如需重寫常用程序的範例，請參閱 [Cypher 重寫](migration-opencypher-rewrites.md)。
  + **[Cypher 執行](https://neo4j.com/labs/apoc/4.2/cypher-execution/)** – Neptune 透過對 OpenCypher 和 Gremlin 查詢語言的支援，支援一組豐富的功能更新屬性圖資料。如需重寫常用程序的範例，請參閱 [Cypher 重寫](migration-opencypher-rewrites.md)。
+ **自訂程序** – Neptune 不支援使用者建立的自訂程序。此功能必須在應用程式層實作。
+ **地理空間** – 雖然 Neptune 不為地理空間功能提供原生支援，但可以透過與其他 AWS 服務整合來實現類似的功能，如這篇部落格文章所示：[合併 Amazon Neptune 和 Amazon OpenSearch Service 進行地理空間查詢](https://aws.amazon.com/blogs/database/combine-amazon-neptune-and-amazon-opensearch-service-for-geospatial-queries/)，作者為 Ross Gabay 和 Abhilash Vinod (2022 年 2 月 1 日)。
+ **圖形資料科學** — 現今 Neptune 透過 [Neptune Analytics](https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html) 支援圖形分析，這是一種支援圖形分析演算法程式庫的記憶體最佳化引擎。

  Neptune 也提供了與 [AWS Pandas SDK](https://github.com/amazon-archives/fully-automated-neo4j-to-neptune) 的整合以及幾個[範例筆記本](https://github.com/aws/graph-notebook/tree/main/src/graph_notebook/notebooks/05-Data-Science)，這些筆記本範例展示如何在 Python 環境內利用此整合，對圖形資料進行分析。

  
+ **結構描述限制條件** – 在 Neptune 內，唯一可用的結構描述限制條件是節點或邊緣 ID 的唯一性。沒有功能可以指定任何其他結構描述限制條件，或指定圖形中元素上的任何其他唯一性或值限制條件。Neptune 中的 ID 值是字串，而且可以使用 Grimlin 進行設定，如下所示：

  ```
  g.addV('person').property(id, '1') )
  ```

  鼓勵需要利用 ID 做為唯一性限制條件的應用程式來試用此方法，實現唯一性限制條件。如果應用程式使用了多個資料行做為唯一性限制條件，則 ID 可能會設定為這些值的組合。例如，`id=123, code='SEA'` 可以表示為 `ID='123_SEA'`，以實現複雜的唯一性限制條件。
+ **多重租用** – Neptune 僅支援每個叢集單一圖形。若要使用 Neptune 建置多租用戶系統，請使用多個叢集，或在單一圖形內以邏輯方式分割租用戶，並使用應用程式端邏輯強制執行分隔。例如，新增屬性 `tenantId` 並將其包含在每個查詢中，如下所示：

  ```
  MATCH p=(n {tenantId:1})-[]->({tenantId:1}) RETURN p LIMIT 5)
  ```

  [Neptune Serverless](neptune-serverless.md) 可讓使用多個資料庫叢集實作多重租用相對容易，每個資料庫叢集都會視需要獨立且自動擴展。

## Neptune 對 Neo4j 工具的支援
<a name="migration-compatibility-tools"></a>

Neptune 提供了 Neo4j 工具的下列替代方案：
+ **[Neo4j Browser](https://neo4j.com/docs/operations-manual/current/installation/neo4j-browser/)** – Neptune 提供開放原始碼[圖形筆記本](graph-notebooks.md)，其中提供以開發人員為中心的 IDE 來執行查詢和視覺化結果。
+ **[Neo4j Bloom](https://neo4j.com/product/bloom/)** – Neptune 支援使用[第三方視覺化解決方案](visualization-tools.md) (例如 Graph-explorer、Tom Sawyer、Cambridge Intelligence、Graphistry、metaphacts 和 G.V()) 進行豐富的圖形視覺化。
+ **[GraphQL](https://graphql.org/)** – Neptune 目前透過自訂 AWS AppSync 整合支援 GraphQL。請參閱[使用 Amazon Neptune 和 AWS Amplify 建置圖形應用程式](https://aws.amazon.com/blogs/database/build-a-graph-application-with-amazon-neptune-and-aws-amplify/)部落格文章，以及範例專案、[使用 AWS AppSync 和 Amazon Neptune 建置 Serverless Calorie 追蹤器應用程式](https://github.com/aws-samples/aws-appsync-calorie-tracker-workshop)。
+ **[NeoSemantics](https://neo4j.com/labs/neosemantics/4.0/)** – Neptune 原本支援 RDF 資料模型，因此建議想要執行 RDF 工作負載的客戶使用 Neptune 的 RDF 模型支援。
+ **[Arrows.app](https://arrows.app/)** – 使用匯出命令匯出模型時建立的 Cypher 與 Neptune 相容。
+ **[Linkurious Ogma](https://doc.linkurious.com/ogma/latest/)**[ – 這裡提供與 Linkurious Ogma](https://github.com/aws-samples/amazon-neptune-samples/tree/master/gremlin/ogma-neptune) 的範例整合。
+ **[Spring Data Neo4j](https://spring.io/projects/spring-data-neo4j)** – 這目前與 Neptune 不相容。
+ **[Neo4j Spark Connector](https://neo4j.com/docs/spark/current/)** – Neo4j Spark Connector 可在 Spark 工作內用來使用 OpenCypher 連線到 Neptune。以下是一些範例程式碼和應用程式組態：

  **範本程式碼：**

  ```
  SparkSession spark = SparkSession
              .builder()
              .config("encryption.enabled", "true")
              .appName("Simple Application").config("spark.master", "local").getOrCreate();
  
  Dataset<Row> df = spark.read().format("org.neo4j.spark.DataSource")
              .option("url", "bolt://(your cluster endpoint):8182")
              .option("encryption.enabled", "true")
              .option("query", "MATCH (n:airport) RETURN n")
              .load();
              
  System.out.println("TOTAL RECORD COUNT: " + df.count());
  spark.stop();
  ```

  **應用程式組態**

  ```
  <dependency>
      <groupId>org.neo4j</groupId>
      <artifactId>neo4j-connector-apache-spark_2.12-4.1.0</artifactId>
      <version>4.0.1_for_spark_3</version>
  </dependency>
  ```

### 這裡未列出的 Neo4j 功能和工具
<a name="migration-compatibility-tools-unlisted"></a>

如果您使用此處未列出的工具或功能，我們不確定其是否與 Neptune 或其他 服務相容 AWS。如果您有其他問題，請聯絡 AWS 支援或與您的客戶團隊互動。

# 重寫 Cypher 查詢以在 Neptune 上的 OpenCpher 中執行
<a name="migration-opencypher-rewrites"></a>

OpenCypher 語言是屬性圖的宣告式查詢語言，最初由 Neo4j 開發，然後在 2015 年成為開放原始碼，並在 Apache 2 開放原始碼授權下投入 [OpenCypher 專案](https://www.opencypher.org/)。在 AWS，我們相信開放原始碼對每個人都有益，我們致力於將開放原始碼的價值帶給客戶，以及將 的卓越營運 AWS 帶給開放原始碼社群。

OpenCypher 語法記載於 [Cypher 查詢語言參考第 9 版](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf)。

由於 OpenCypher 包含 Cypher 查詢語言的語法和功能子集，因此某些遷移案例需要以 OpenCypherr 相容的格式重寫查詢，或檢查替代方法以實現所需的功能。

本節包含處理常見差異的建議，但它們絕不是全面的。您應該使用這些重寫徹底測試任何應用程式，以確保結果就是您預期的。

## 重寫 `None`、`All` 和 `Any` 述詞函數
<a name="migration-opencypher-rewrites-none-all-any"></a>

這些函數不是 openCypher 規格的一部分。可比較的結果可以在 OpenCypher 中使用清單理解來實現。

例如，尋找從節點 `Start` 到節點 `End` 的所有路徑，但不允許任何行程通過類別屬性為 `D` 的節點：

```
# Neo4J Cypher code
match p=(a:Start)-[:HOP*1..]->(z:End)
where none(node IN nodes(p) where node.class ='D')
return p

# Neptune openCypher code
match p=(a:Start)-[:HOP*1..]->(z:End)
where size([node IN nodes(p) where node.class = 'D']) = 0
return p
```

清單理解可以實現這些結果，如下所示：

```
all  => size(list_comprehension(list)) = size(list)
any  => size(list_comprehension(list)) >= 1
none => size(list_comprehension(list)) = 0
```

## 在 openCypher 中重寫 Cypher `reduce()` 函數
<a name="migration-opencypher-rewrites-reduce"></a>

`reduce()` 函數不是 openCypher 規格的一部分。它通常用來從清單內的元素建立資料的彙總。在許多情況下，您可以使用清單理解和 `UNWIND` 子句的組合來實現類似的結果。

例如，在安克雷奇 (ANC) 與奧斯汀 (AUS) 之間具有一到三個停靠站的路徑上，下列 Cypher 查詢會找出所有位於這些路徑上的機場，並傳回每條路徑的總距離：

```
MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'})
RETURN p, reduce(totalDist=0, r in relationships(p) | totalDist + r.dist) AS totalDist
ORDER BY totalDist LIMIT 5
```

您可以在 OpenCypher 為 Neptune 編寫相同的查詢，如下所示：

```
MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'})
UNWIND [i in relationships(p) | i.dist] AS di
RETURN p, sum(di) AS totalDist
ORDER BY totalDist
LIMIT 5
```

## 在 openCypher 中重寫 Cypher FOREACH 子句
<a name="migration-opencypher-rewrites-foreach"></a>

FOREACH 子句不是 openCypher 規格的一部分。它通常用來在查詢過程中更新資料，通常是從路徑內的彙總或元素中更新資料。

作為一個路徑範例，在安克雷奇 (ANC) 與奧斯汀 (AUS) 之間不超過兩個停靠站的路徑上，找出所有位於該路徑的機場，並對每個機場設定已訪問屬性：

```
# Neo4J Example
MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'})
FOREACH (n IN nodes(p) | SET n.visited = true)

# Neptune openCypher
MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'})
WITH nodes(p) as airports
UNWIND airports as a
SET a.visited=true
```

另一個範例是：

```
# Neo4J Example
MATCH p=(start)-[*]->(finish)
WHERE start.name = 'A' AND finish.name = 'D'
FOREACH (n IN nodes(p) | SET n.marked = true)

# Neptune openCypher
MATCH p=(start)-[*]->(finish)
WHERE start.name = 'A' AND finish.name = 'D'
UNWIND nodes(p) AS n
SET n.marked = true
```

## 在 Neptune 中重寫 NEO4j APOC 程序
<a name="migration-opencypher-rewrites-apoc"></a>

下面範例會使用 openCypher 來取代一些最常用的 [APOC 程序](https://neo4j.com/blog/intro-user-defined-procedures-apoc/)。這些範例僅供參考，旨在提供一些有關如何處理常見案例的建議。實際上，每個應用程序都有所不同，您必須制定自己的策略來提供您需要的所有功能。

### 重寫 `apoc.export` 程序
<a name="migration-opencypher-rewrites-apoc-export"></a>

Neptune 會使用 [neptune-export](https://github.com/aws/neptune-export) 公用程式，為各種輸出格式 (例如 CSV 和 JSON) 的完整圖形和查詢型匯出提供一系列選項 (請參閱 [從 Neptune 資料庫叢集匯出資料](neptune-data-export.md))。

### 重寫 `apoc.schema` 程序
<a name="migration-opencypher-rewrites-apoc-schema"></a>

Neptune 沒有明確定義的結構描述、索引或限制條件，因此不再需要許多 `apoc.schema` 程序。範例如下：
+ `apoc.schema.assert`
+ `apoc.schema.node.constraintExists`
+ `apoc.schema.node.indexExists`,
+ `apoc.schema.relationship.constraintExists`
+ `apoc.schema.relationship.indexExists`
+ `apoc.schema.nodes`
+ `apoc.schema.relationships`

Neptune OpenCypher 確實支援擷取的值與程序擷取的值類似，如下所示，但可能會在較大的圖形上遇到效能問題，因為這樣做需要掃描圖形的大部分才能返回答案。

```
# openCypher replacement for apoc.schema.properties.distinct
MATCH (n:airport)
RETURN DISTINCT n.runways
```

```
# openCypher replacement for apoc.schema.properties.distinctCount
MATCH (n:airport)
RETURN DISTINCT n.runways, count(n.runways)
```

### `apoc.do` 程序的替代方案
<a name="migration-opencypher-rewrites-apoc-do"></a>

這些程序是用來提供條件式查詢執行，很容易使用其他 OpenCypher 子句來實作。在 Neptune 中，至少有兩種方法可以實現類似的行為：
+ 一種方法是將 OpenCypher 的清單理解功能與 `UNWIND` 子句結合。
+ 另一種方法是在 Gremlin 中使用 choose() 和 coalesce() 步驟。

這些方法的範例如下所示。

#### apoc.do.when 的替代方案
<a name="migration-opencypher-rewrites-apoc-do-when"></a>

```
# Neo4J Example
MATCH (n:airport {region: 'US-AK'})
CALL apoc.do.when(
 n.runways>=3,
 'SET n.is_large_airport=true RETURN n',
 'SET n.is_large_airport=false RETURN n',
 {n:n}
) YIELD value
WITH collect(value.n) as airports
RETURN size([a in airports where a.is_large_airport]) as large_airport_count,
size([a in airports where NOT a.is_large_airport]) as small_airport_count


# Neptune openCypher
MATCH (n:airport {region: 'US-AK'})
WITH n.region as region, collect(n) as airports
WITH [a IN airports where a.runways >= 3] as large_airports,
[a IN airports where a.runways < 3] as small_airports, airports
UNWIND large_airports as la
SET la.is_large_airport=true
WITH DISTINCT small_airports, airports
UNWIND small_airports as la
    SET la.small_airports=true
WITH DISTINCT airports
RETURN size([a in airports where a.is_large_airport]) as large_airport_count,
size([a in airports where NOT a.is_large_airport]) as small_airport_count

#Neptune Gremlin using choose()
g.V().
  has('airport', 'region', 'US-AK').
  choose(
    values('runways').is(lt(3)),
    property(single, 'is_large_airport', false),
    property(single, 'is_large_airport', true)).
  fold().
  project('large_airport_count', 'small_airport_count').
    by(unfold().has('is_large_airport', true).count()).
    by(unfold().has('is_large_airport', false).count())

 #Neptune Gremlin using coalesce() 
g.V().
  has('airport', 'region', 'US-AK').
  coalesce(
    where(values('runways').is(lt(3))).
    property(single, 'is_large_airport', false),
    property(single, 'is_large_airport', true)).
  fold().
  project('large_airport_count', 'small_airport_count').
    by(unfold().has('is_large_airport', true).count()).
    by(unfold().has('is_large_airport', false).count())
```

#### apoc.do.case 的替代方案
<a name="migration-opencypher-rewrites-apoc-do-case"></a>

```
# Neo4J Example
MATCH (n:airport {region: 'US-AK'})
CALL apoc.case([
 n.runways=1, 'RETURN "Has one runway" as b',
 n.runways=2, 'RETURN "Has two runways" as b'
 ],
 'RETURN "Has more than 2 runways" as b'
) YIELD value 
RETURN {type: value.b,airport: n}

# Neptune openCypher
MATCH (n:airport {region: 'US-AK'})
WITH n.region as region, collect(n) as airports
WITH [a IN airports where a.runways =1] as single_runway,
[a IN airports where a.runways =2] as double_runway,
[a IN airports where a.runways >2] as many_runway
UNWIND single_runway as sr
    WITH {type: "Has one runway",airport: sr} as res, double_runway, many_runway
WITH DISTINCT double_runway as double_runway, collect(res) as res, many_runway
UNWIND double_runway as dr
    WITH {type: "Has two runways",airport: dr} as two_runways, res, many_runway
WITH collect(two_runways)+res as res, many_runway
UNWIND many_runway as mr
    WITH {type: "Has more than 2 runways",airport: mr} as res2, res, many_runway
WITH collect(res2)+res as res
UNWIND res as r
RETURN r

#Neptune Gremlin using choose()
g.V().
  has('airport', 'region', 'US-AK').
  project('type', 'airport').
    by(
      choose(values('runways')).
        option(1, constant("Has one runway")).
        option(2, constant("Has two runways")).
        option(none, constant("Has more than 2 runways"))).
    by(elementMap())

 #Neptune Gremlin using coalesce()
 g.V().
  has('airport', 'region', 'US-AK').
  project('type', 'airport').
    by(
      coalesce(
        has('runways', 1).constant("Has one runway"),
        has('runways', 2).constant("Has two runways"),
        constant("Has more than 2 runways"))).
    by(elementMap())
```

## 清單型屬性的替代方案
<a name="migration-opencypher-rewrites-lists"></a>

Neptune 目前不支援儲存清單型屬性。不過，您可以將清單值儲存為逗號分隔字串，然後使用 `join()` 和 `split()` 函數來建構和解構清單屬性，以取得類似的結果。

例如，如果想要將標籤清單儲存為屬性，則可以使用重寫範例，其中展示如何擷取逗號分隔屬性，然後使用 `split()` 和 `join()` 函數搭配清單理解來實現可比較的結果：

```
# Neo4j Example (In this example, tags is a durable list of string.
MATCH (person:person {name: "TeeMan"})
WITH person, [tag in person.tags WHERE NOT (tag IN ['test1', 'test2', 'test3'])] AS newTags
SET person.tags = newTags
RETURN person

# Neptune openCypher 
MATCH (person:person {name: "TeeMan"})
WITH person, [tag in split(person.tags, ',') WHERE NOT (tag IN ['test1', 'test2', 'test3'])] AS newTags
SET person.tags = join(newTags,',')
RETURN person
```

## 重寫 CALL 子查詢
<a name="migration-opencypher-rewrites-call-subqueries"></a>

 Neptune `CALL`子查詢不支援將變數匯入子查詢範圍`CALL (friend) { ... }`的語法 （在此範例中`friend`為 )。請針對相同的子查詢使用 `WITH`子句，例如 `CALL { WITH friend ... }`。

 目前不支援選用`CALL`的子查詢。

## Neptune openCypher 與 Cypher 之間的其他差異
<a name="opencypher-compliance-other-differences"></a>
+ Neptune 僅支援 Bolt 通訊協定的 TCP 連線。不支援 Bolt 的 WebSockets 連線。
+ Neptune openCypher 會移除 `trim()`、`ltrim()` 和 `rtrim()` 函數中由 Unicode 定義的空格。
+ 在 Neptune OpenCypher 中，`tostring(`double`)` 不會自動切換到 E 表示法，表示 double 的大值。

# 從 Neo4j 遷移到 Neptune 的資源
<a name="migration-resources"></a>

Neptune 提供數個可協助遷移程序的工具和資源。

**協助從 Neo4j 遷移到 Neptune 的工具**
+ openCypher [CheatSheet](https://github.com/aws-samples/amazon-neptune-samples/blob/master/opencypher/Cheatsheet.md)。
+ [neo4j-to-neptune](https://github.com/awslabs/amazon-neptune-tools/tree/master/neo4j-to-neptune) – 命令列公用程式，用於將資料從 Neo4j 遷移至 Neptune。此工具包含以下功能：
  + 從正確設定的 Neo4j 圖形匯出資料。
  + 將該資料轉換為 Neptune 格式。
  + 將資料大量載入 Neptune。
  + 在轉換為 Neptune 格式期間執行一些基本的資料轉換，例如重新命名頂點或邊緣標籤和產生元素。
  + 使用 範本產生節點和邊緣的屬性 （例如，針對您需要為 元素建立唯一識別符的情況，使用 範本建立 `~id`值，例如 `Person_{personid}` )。
+ [openCypher 查詢相容性檢查程式](https://github.com/awslabs/amazon-neptune-tools/tree/master/opencypher-compatability-checker) – 此工具接受 openCypher 查詢的輸入，並將：
  + 檢查與所選 Neptune 版本的相容性。
  + 識別特定不支援的函數和子句及其位置。
  + 如果可用，建議替換。
  + 提供任何其他語法錯誤的錯誤描述。