

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

# 使用 Gremlin 搭配 Neptune 的一般最佳實務
<a name="best-practices-gremlin"></a>

使用 Gremlin 圖形周遊語言搭配 Neptune 時，請遵循這些建議。如需使用 Gremlin 搭配 Neptune 的詳細資訊，請參閱 [使用 Gremlin 存取 Neptune 圖形](access-graph-gremlin.md)。

**重要**  
已在 TinkerPop 3.4.11 版中進行變更，這可提高查詢處理方式的正確性，但目前有時可能會嚴重影響查詢效能。  
例如，此類查詢的執行速度可能會明顯變慢：  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  out()
```
由於 TinkerPop 3.4.11 變更，限制步驟之後的頂點現在會以非最佳方式擷取。若要避免這種情況，您可以在 `order().by()` 之後的任何點新增 barrier() 步驟來修改查詢。例如：  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  barrier().
  out()
```
TinkerPop 3.4.11 已在 [Neptune 引擎 1.0.5.0 版](engine-releases-1.0.5.0.md)中啟用。

**Topics**
+ [Neptune Serverless 的活動訊號組態](best-practices-gremlin-heartbeat-serverless.md)
+ [建造 upsert 查詢以利用 DFE 引擎](#best-practices-gremlin-upserts)
+ [在您將部署 Girmlin 程式碼的內容中測試該程式碼](best-practices-gremlin-console-glv-differences.md)
+ [建立有效率的多執行緒 Gremlin 寫入](best-practices-gremlin-multithreaded-writes.md)
+ [利用建立時間屬性清除記錄](best-practices-gremlin-prune.md)
+ [對 Groovy 時間資料使用 `datetime( )` 方法](best-practices-gremlin-datetime.md)
+ [在 GLV 時間資料使用原生日期和時間](best-practices-gremlin-datetime-glv.md)

# Neptune Serverless 的活動訊號組態
<a name="best-practices-gremlin-heartbeat-serverless"></a>

搭配 Neptune Serverless 使用 Gremlin WebSocket 用戶端時，您需要適當設定用戶端的 ping 間隔，以在擴展事件期間維持穩定的連線。Gremlin 用戶端使用 WebSocket 連線，並傳送定期 ping 以確認連線作用中。用戶端預期伺服器會在 ping 間隔時間範圍內回應。如果伺服器未回應，用戶端會自動關閉連線。

對於 Neptune **佈建的**執行個體，我們建議將 ping 間隔設定為 **5 秒**。對於 Neptune **Serverless 叢集**，我們建議將 ping 間隔設定為至少 **20 秒**，以適應擴展操作期間的潛在延遲。此參數控制用戶端在寫入伺服器之間等待多久，再傳送 ping 以確認連線仍然作用中。

此參數的組態會根據用戶端實作而有所不同：

**Java 用戶端組態**

針對 Java TinkerPop Gremlin 用戶端，設定 `keepAliveInterval` 參數：

```
Cluster.Builder builder = Cluster.build()
    .addContactPoint(endpoint)
    .keepAliveInterval(20000); // Configure ping interval in milliseconds
```

如需 Java 驅動程式組態的詳細資訊，請參閱 [Java TinkerPop 文件](https://tinkerpop.apache.org/docs/current/reference/#gremlin-java-configuration)。

**Go 用戶端組態**

針對 Gremlin Go 用戶端，設定 `KeepAliveInterval` 參數：

```
rc, err := driver.NewDriverRemoteConnection(endpoint,
    func(settings *driver.DriverRemoteConnectionSettings) {
        settings.TraversalSource = "g"
        settings.AuthInfo = auth
        settings.KeepAliveInterval = 20 * time.Second // Configure ping interval
        ...
    })
```

如需 Go 驅動程式組態的詳細資訊，請參閱 [Go TinkerPop 文件](https://tinkerpop.apache.org/docs/current/reference/#gremlin-go-configuration)。

**JavaScript/Node.js 用戶端組態**

針對 JavaScript/Node.js Gremlin 用戶端，設定 `pingInterval` 參數：

```
const gremlin = require('gremlin');
const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;

const connection = new DriverRemoteConnection(endpoint, {
    traversalSource: 'g',
    pingInterval: 20000  // Configure ping interval in milliseconds
});
```

如需 JavaScript 驅動程式組態的詳細資訊，請參閱 [JavaScript TinkerPop 文件](https://tinkerpop.apache.org/docs/current/reference/#gremlin-javascript-configuration)。

**Python 用戶端組態**

對於 Python Gremlin 用戶端，ping 間隔通常在傳輸層進行管理。如需組態選項，請參閱特定的傳輸實作文件：

```
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection

g = traversal().with_remote(
    DriverRemoteConnection('wss://your-neptune-endpoint:your-neptune-port/gremlin','g',
        transport_factory=lambda: AiohttpTransport(read_timeout=60,
                                                    write_timeout=20,
                                                    heartbeat=20, // Configure heartbeat
                                                    call_from_event_loop=True,
                                                    max_content_length=100*1024*1024,
                                                    ssl_options=ssl.create_default_context(Purpose.CLIENT_AUTH))))
```

如需 Python 驅動程式組態的詳細資訊，請參閱 [Python TinkerPop 文件](https://tinkerpop.apache.org/docs/current/reference/#gremlin-python-configuration)。

此組態可確保用戶端在 Neptune Serverless 擴展事件期間維持連線穩定性，防止不必要的連線關閉並改善應用程式可靠性。

## 建造 upsert 查詢以利用 DFE 引擎
<a name="best-practices-gremlin-upserts"></a>

[使用 Gremlin `mergeV()` 和 `mergeE()` 步驟進行有效的 upsert](gremlin-efficient-upserts.md) 說明如何建造 upsert 查詢，以盡可能有效地使用 DFE 引擎。

# 在您將部署 Girmlin 程式碼的內容中測試該程式碼
<a name="best-practices-gremlin-console-glv-differences"></a>

在 Gemlin 中，有多種方式可讓用戶端將查詢提交至伺服器：使用 WebSocket 或位元碼 GLV，或透過使用字串型指令碼的 Gemlin 控制台。

務必認識到 Gemlin 查詢執行可能會有所不同，取決於您提交查詢的方式。如果在位元碼模式下提交，則傳回空結果的查詢可能會被視為成功，但如果在指令碼模式下提交，則可能會被視為失敗。例如，如果您在指令碼模式查詢中包含 `next()`，則 `next()` 會傳送至伺服器，但是用戶端通常會使用位元碼來處理 `next()` 本身。在第一種情況下，如果找不到任何結果，查詢就會失敗，但在第二種情況下，無論結果集是否為空，查詢都會成功。

如果您在某個內容中開發並測試您的程式碼 (例如，通常以文字形式提交查詢的 Gemlin 控制台)，但是接著在不同的內容中部署程式碼 (例如，透過使用位元碼的 Java 驅動程式)，則您可能會遇到下列問題：程式碼在生產環境中的行為與在開發環境中的行為不同。

**重要**  
務必在將要部署 Gremlin 程式碼的 GLV 內容中測試該程式碼，以避免發生非預期的結果。

# 建立有效率的多執行緒 Gremlin 寫入
<a name="best-practices-gremlin-multithreaded-writes"></a>

使用 Gremlin 以多執行緒的方式將資料載入 Neptune，有幾項準則。

如有可能，請提供每個執行緒一組頂點或邊緣，以插入或修改不衝突的項目。例如，執行緒 1 的地址 ID 範圍為 1–50,000，執行緒 2 地址 ID 範圍為 50,001–100,000，以此類推。這可減少出現 `ConcurrentModificationException` 的機率。為安全起見，所有寫入請圍以 `try/catch` 區塊。若任何一個項目失敗，您便可以在短暫的延遲後重試它們。

以介於 50 和 100 (頂點或邊緣) 間的批次大小批次寫入，通常效果很好。若您要為每個頂點新增許多屬性，接近 50 的數字可能比接近 100 的數字更好。這很值得進行一些實驗。因此針對批次寫入，您可以使用如下的內容：

```
g.addV(‘test’).property(id,’1’).as(‘a’).
  addV(‘test’).property(id,’2’).
  addE(‘friend’).to(‘a’).
```

接著會在每一個批次操作中重複這段過程。

使用批次的效率，遠比在每一次 Gremlin 與伺服器的來回行程中新增一個頂點或邊緣高。

如果您使用的是 Gremlin 語言變體 (GLV) 用戶端，您可以先建立一個周遊，再以程式設計方式建立一個批次。然後，為它新增內容，最後再對它反覆運算，例如：

```
  t.addV(‘test’).property(id,’1’).as(‘a’)
  t.addV(‘test’).property(id,’2’)
  t.addE(‘friend’).to(‘a’)
  t.iterate()
```

如果可能，最好使用 Gremlin 語言變體用戶端。但是，您可以串連字串來建立批次，用將查詢提交為文字字串的用戶端執行類似的作業。

若您使用其中一個 Gremlin 用戶端程式庫，而非基本的 HTTP 來進行查詢，則執行緒應該全部都會共享相同的用戶端、叢集或連線集區。您可能需要調校設定，來盡可能取得最佳的輸送量，像是 Gremlin 用戶端所使用的連線集區大小及工作者執行緒數量等設定。

# 利用建立時間屬性清除記錄
<a name="best-practices-gremlin-prune"></a>

您可以把建立時間儲存為頂點上的屬性，然後定期丟棄它們，藉此清除過時記錄。

如果需要讓資料存放一段特定時間，然後從圖形中移除 (頂點存留時間)，您可以在建立頂點時儲存時間戳記屬性。然後，您可以定期對所有在特定時間前建立的頂點發出 `drop()` 查詢，例如：

```
g.V().has(“timestamp”, lt(datetime('2018-10-11')))
```

# 對 Groovy 時間資料使用 `datetime( )` 方法
<a name="best-practices-gremlin-datetime"></a>

Neptune 會提供 `datetime` 方法，為 Gremlin **Groovy** 變體中傳送的查詢指定日期和時間。這包括 Gremlin 主控台、使用 HTTP REST API 的文字字串，以及任何其他使用 Groovy 的序列化。

**重要**  
這「只」**適用於以「文字字串」**傳送 Gremlin 查詢的方法。如果使用的是 Gremlin 語言變體，您必須使用該語言的原生日期類別與函數。如需詳細資訊，請參閱下一節「[在 GLV 時間資料使用原生日期和時間](best-practices-gremlin-datetime-glv.md)」。  
從 TinkerPop `3.5.2` (在 [Neptune 引擎 1.1.1.0 版](engine-releases-1.1.1.0.md) 中引入) 開始，`datetime` 是 TinkerPop 不可或缺的一部分。

您可以使用 `datetime` 方法來存放和比較日期：

```
g.V('3').property('date',datetime('2001-02-08'))
```

```
g.V().has('date',gt(datetime('2000-01-01')))
```

# 在 GLV 時間資料使用原生日期和時間
<a name="best-practices-gremlin-datetime-glv"></a>

如果您是使用 Gremlin 語言變體 (GLV)，必須使用該程式語言為 Gremlin 時間資料提供的原生日期和時間類別與函數。

官方 TinkerPop 程式庫都是 Gremlin 語言變體程式庫。
+  [Go](https://tinkerpop.apache.org/docs/current/reference/#gremlin-go) 
+  [Java](https://tinkerpop.apache.org/docs/current/reference/#gremlin-java) 
+  [Javascript](https://tinkerpop.apache.org/docs/current/reference/#gremlin-javascript) 
+  [.NET](https://tinkerpop.apache.org/docs/current/reference/#gremlin-dotnet) 
+  [Python](https://tinkerpop.apache.org/docs/current/reference/#gremlin-python) 

**重要**  
 此頁面僅適用於 Gremlin 語言變體 (GLV) 程式庫。如果您使用將 Gremlin 查詢作為文字字串傳送的方法，則必須使用 Gremlin 的日期時間 () 函數。這包括 Gremlin 主控台、使用 HTTP REST API 的文字字串，或透過驅動程式直接提交 Gremlin 字串。



**Go**  
 以下是 Go 中的部分範例，該範例會為 ID 為 '3' 的頂點建立名為 'date' 的單一屬性。它將值設定為使用 Go time.Now() 函數產生的日期。

```
import ( "time" )

g.V('3').property('date', time.Now()).next();
```

如需使用 Go 連線至 Neptune 的完整範例，請參閱[使用 Go 用戶端連線至 Neptune 資料庫執行個體](https://docs.aws.amazon.com//neptune/latest/userguide/access-graph-gremlin-go.html)。

**Java**  
以下是 Java 範例的一部分，它會為頂點建立一個名為 '`date`' 且 ID 為 '`3`' 的屬性。它將值設為使用 Java `Date()` 建構函數產生的日期。

```
import java.util.date

g.V('3').property('date', new Date()).next();
```

如需使用 Java 連線至 Neptune 的完整範例，請參閱 [使用 Java 連線至 Neptune 資料庫執行個體](access-graph-gremlin-java.md)。

**Node.js (JavaScript)**  
以下是 JavaScript 範例的一部分，它會為頂點建立一個名為 '`date`' 且 ID 為 '`3`' 的屬性。它將值設為使用 Node.js `Date()` 建構函數產生的日期。

```
g.V('3').property('date', new Date()).next()
```

如需使用 Node.js 連線至 Neptune 的完整範例，請參閱 [使用 Node.js 連線至 Neptune 資料庫執行個體](access-graph-gremlin-node-js.md)。

**.NET (C\$1)**  
以下是 C\$1 範例的一部分，它會為頂點建立一個名為 '`date`' 且 ID 為 '`3`' 的屬性。它將值設為使用 .NET `DateTime.UtcNow` 屬性產生的日期。

```
Using System;

g.V('3').property('date', DateTime.UtcNow).next()
```

如需使用 C\$1 連線至 Neptune 的完整範例，請參閱 [使用 .NET 連線至 Neptune 資料庫執行個體](access-graph-gremlin-dotnet.md)。

**Python**  
以下是 Python 範例的一部分，它會為頂點建立一個名為 '`date`' 且 ID 為 '`3`' 的屬性。它將值設為使用 Python `datetime.now()` 方法產生的日期。

```
import datetime

g.V('3').property('date',datetime.datetime.now()).next()
```

如需使用 Python 連線至 Neptune 的完整範例，請參閱 [使用 Python 連線至 Neptune 資料庫執行個體](access-graph-gremlin-python.md)。