

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

# 将 Gremlin 与 Neptune 结合使用的一般最佳实践
<a name="best-practices-gremlin"></a>

在将 Gremlin 图形遍历语言与 Neptune 一起使用时，请遵循以下建议。有关将 Gremlin 与 Neptune 一起使用的信息，请参阅[使用 Gremlin 访问 Neptune 图形](access-graph-gremlin.md)。

**重要**  
3.4.11 TinkerPop 版本中进行了更改，提高了查询处理方式的正确性，但目前有时会严重影响查询性能。  
例如，这种查询的运行速度可能会慢得多：  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  out()
```
由于 3.4.11 的更改，极限步骤之后的顶点现在以非最佳方式获取。 TinkerPop 为避免这种情况，您可以通过在 `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 无服务器的心跳配置](best-practices-gremlin-heartbeat-serverless.md)
+ [构建更新插入查询以利用 DFE 引擎](#best-practices-gremlin-upserts)
+ [在要部署 Gremlin 代码的上下文中对其进行测试](best-practices-gremlin-console-glv-differences.md)
+ [创建高效的多线程 Gremlin 写入](best-practices-gremlin-multithreaded-writes.md)
+ [使用创建时间属性修剪记录](best-practices-gremlin-prune.md)
+ [将 `datetime( )` 方法用于 Groovy 时间数据](best-practices-gremlin-datetime.md)
+ [将本机日期和时间用于 GLV 时间数据](best-practices-gremlin-datetime-glv.md)

# Neptune 无服务器的心跳配置
<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 扩展事件期间保持连接稳定性，从而防止不必要的连接关闭并提高应用程序的可靠性。

## 构建更新插入查询以利用 DFE 引擎
<a name="best-practices-gremlin-upserts"></a>

[使用 Gremlin `mergeV()` 和 `mergeE()` 步骤进行高效的更新插入](gremlin-efficient-upserts.md)解释了如何构建更新插入查询以尽可能有效地使用 DFE 引擎。

# 在要部署 Gremlin 代码的上下文中对其进行测试
<a name="best-practices-gremlin-console-glv-differences"></a>

在 Gremlin 中，客户端可以通过多种方式向服务器提交查询：使用 WebSocket、或 Bytecode GLV，或者使用基于字符串的脚本通过 Gremlin 控制台。

务必认识到，根据您提交查询的方式，Gremlin 查询执行可能会有所不同。如果在字节码模式下提交，返回空结果的查询可能会视为成功，但如果在脚本模式下提交，则视为失败。例如，如果您包含`next()`在脚本模式查询中，`next()`则会将发送到服务器，但使用 ByteCode 客户端通常会自行处理。`next()`在第一种情况下，如果未找到任何结果，查询就会失败；但在第二种情况下，无论结果集是否为空，查询都会成功。

如果您在一个上下文中开发和测试代码（例如，通常以文本形式提交查询的 Gremlin 控制台），但随后在不同的上下文中部署代码（例如，通过使用字节码的 Java 驱动程序），则可能会遇到问题，即代码在生产环境中的行为与在开发环境中的行为不同。

**重要**  
请务必在将要部署 Gremlin 代码的 GLV 环境中测试该代码，以免出现意外结果。

# 创建高效的多线程 Gremlin 写入
<a name="best-practices-gremlin-multithreaded-writes"></a>

使用 Gremlin 将数据通过多线程加载到 Neptune 时，有一些指导方针可供遵循。

如果有可能，向每个线程提供一组可以插入或修改而不造成冲突的顶点或边缘。例如，线程 1 地址 ID 范围是 1–50000，线程 2 地址 ID 范围是 50001–100000，以此类推。这会减少造成 `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')))
```

# 将 `datetime( )` 方法用于 Groovy 时间数据
<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 的 datetime() 函数。这包括 Gremlin 控制台、使用 HTTP REST API 的文本字符串或通过驱动程序直接提交的 Gremlin 字符串。



**Go**  
 下面是采用 Go 的示例的一部分，该示例为 ID 是“3”的顶点创建名为“日期”的单个属性。它将该值设置为使用 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 的示例的一部分，该示例为 ID 为“`3`”的顶点创建名为“`date`”的单个属性。它将值设置为使用 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`” 的顶点创建了一个名为 “`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 的示例的一部分，该示例为 ID 为“`3`”的顶点创建名为“`date`”的单个属性。它将值设置为使用 .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 的示例的一部分，该示例为 ID 是“`3`”的顶点创建名为“`date`”的单个属性。它将值设置为使用 Python `datetime.now()` 方法生成的日期。

```
import datetime

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

有关使用 Python 连接到 Neptune 的完整示例，请参阅[使用 Python 连接到 Neptune 数据库实例](access-graph-gremlin-python.md)。