

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Accès au graphe Neptune avec Gremlin
<a name="access-graph-gremlin"></a>

Amazon Neptune est compatible avec Apache TinkerPop et Gkremlin. Cela signifie que vous pouvez vous connecter à une instance de base de données Neptune et utiliser le langage de traversée Gremlin pour interroger le graphe (voir The Graph dans [la documentation d'Apache](https://tinkerpop.apache.org/docs/current/reference/#graph)). TinkerPop Pour voir les différences dans l'implémentation Neptune de Gremlin, consultez [Conformité avec les normes Gremlin](access-graph-gremlin-differences.md).

 Une *traversée* dans Gremlin est une série d'étapes chaînées. Elle commence à un sommet (ou arc). Elle parcourt le graphe en suivant les arêtes extérieures de chaque sommet, puis les arêtes extérieures de ces sommets. Chaque étape représente une opération de la traversée. Pour plus d'informations, consultez [The Traversal](https://tinkerpop.apache.org/docs/current/reference/#traversal) dans la TinkerPop documentation.

Les différentes versions du moteur Neptune prennent en charge différentes versions de Gremlin. Consultez la [page de version du moteur](engine-releases.md) de la version de Neptune que vous utilisez pour déterminer quelle version de Gremlin est prise en charge ou consultez le tableau suivant qui répertorie les versions les plus anciennes et les plus récentes TinkerPop prises en charge par les différentes versions du moteur Neptune :


| Version du moteur Neptune |  TinkerPop Version minimale |  TinkerPop Version maximale | 
| --- | --- | --- | 
| `1.3.2.0 and newer` | `3.7.1` | `3.7.3` | 
| `1.3.1.0` | `3.6.2` | `3.6.5` | 
| `1.3.0.0` | `3.6.2` | `3.6.4` | 
| `1.2.1.0 <= 1.2.1.2` | `3.6.2` | `3.6.2` | 
| `1.1.1.0 <= 1.2.0.2` | `3.5.5` | `3.5.6` | 
| `1.1.0.0 and older` | `(deprecated)` | `(deprecated)` | 

TinkerPop les clients sont généralement rétrocompatibles au sein d'une série (par exemple`3.6.x`, ou`3.7.x`) et bien qu'ils puissent souvent travailler au-delà de ces limites, le tableau ci-dessus recommande les combinaisons de versions à utiliser pour une expérience et une compatibilité optimales. Sauf avis contraire, il est généralement préférable de respecter ces directives et de mettre à niveau les applications clientes pour qu'elles correspondent à la version TinkerPop que vous utilisez.

Lors de la mise à niveau des TinkerPop versions, il est toujours important [TinkerPopde consulter la documentation de mise](http://tinkerpop.apache.org/docs/current/upgrade/) à niveau qui vous aidera à identifier les nouvelles fonctionnalités dont vous pouvez tirer parti, mais également les problèmes dont vous devrez peut-être être conscient à l'approche de votre mise à niveau. Vous devez généralement vous attendre à ce que les requêtes et fonctionnalités existantes fonctionnent après la mise à niveau, sauf si un problème particulier est indiqué comme un problème à prendre en compte. Enfin, il est important de noter que si vous mettez à niveau une version pour intégrer une nouvelle fonctionnalité, vous ne pourrez peut-être pas l'utiliser si elle provient d'une version ultérieure à celle prise en charge par Neptune.

Il existe des variantes du langage Gremlin et une prise en charge de l'accès Gremlin dans les différents langages de programmation. Pour plus d'informations, voir À [propos des variantes linguistiques de Gremlin](https://tinkerpop.apache.org/docs/current/reference/#gremlin-drivers-variants) dans la TinkerPop documentation.

Cette documentation décrit comment accéder à Neptune avec les variantes et langages de programmation suivants :
+ [Configuration de la console Gremlin pour se connecter à une instance de base de données Neptune](access-graph-gremlin-console.md)
+ [Utilisation du point de terminaison HTTP REST pour se connecter à une instance de base de données Neptune](access-graph-gremlin-rest.md)
+ [Clients Gremlin basés sur Java à utiliser avec Amazon Neptune](access-graph-gremlin-client.md)
+ [Utilisation de Python pour se connecter à une instance de base de données Neptune](access-graph-gremlin-python.md)
+ [Utilisation de .NET pour se connecter à une instance de base de données Neptune](access-graph-gremlin-dotnet.md)
+ [Utilisation de Node.js pour se connecter à une instance de base de données Neptune](access-graph-gremlin-node-js.md)
+ [Utilisation de Go pour se connecter à une instance de base de données Neptune](access-graph-gremlin-go.md)

Comme indiqué dans la section[Chiffrement des connexions à votre base de données Amazon Neptune avec SSL/HTTPS](security-ssl.md), vous devez utiliser le protocole TLS/SSL (Transport Security/Secure Layer Sockets Layer) lorsque vous vous connectez à Neptune dans toutes les régions. AWS 

Avant de commencer, les prérequis suivants doivent être remplis :
+ Vous devez disposer d'une instance de base de données Neptune. Pour plus d'informations sur la création d'une instance de base de données Neptune, consultez [Création d'un cluster Amazon Neptune](get-started-create-cluster.md).
+ Vous devez disposer d'une instance Amazon EC2 dans le même cloud privé virtuel (VPC) que l'instance de base de données Neptune.

Pour plus d'informations sur le chargement des données dans Neptune, y compris les prérequis, les formats de chargement et les paramètres de chargement, consultez [Chargement de données dans Amazon Neptune](load-data.md).

**Topics**
+ [Configuration de la console Gremlin pour se connecter à une instance de base de données Neptune](access-graph-gremlin-console.md)
+ [Utilisation du point de terminaison HTTP REST pour se connecter à une instance de base de données Neptune](access-graph-gremlin-rest.md)
+ [Clients Gremlin basés sur Java à utiliser avec Amazon Neptune](access-graph-gremlin-client.md)
+ [Utilisation de Python pour se connecter à une instance de base de données Neptune](access-graph-gremlin-python.md)
+ [Utilisation de .NET pour se connecter à une instance de base de données Neptune](access-graph-gremlin-dotnet.md)
+ [Utilisation de Node.js pour se connecter à une instance de base de données Neptune](access-graph-gremlin-node-js.md)
+ [Utilisation de Go pour se connecter à une instance de base de données Neptune](access-graph-gremlin-go.md)
+ [Utiliser le AWS SDK pour exécuter des requêtes Gremlin](access-graph-gremlin-sdk.md)
+ [Indicateurs de requête Gremlin](gremlin-query-hints.md)
+ [API de statut des requêtes Gremlin](gremlin-api-status.md)
+ [Annulation de requêtes Gremlin](gremlin-api-status-cancel.md)
+ [Prise en charge des sessions basées sur des scripts Gremlin](access-graph-gremlin-sessions.md)
+ [Transactions Gremlin dans Neptune](access-graph-gremlin-transactions.md)
+ [Utilisation de l'API Gremlin avec Amazon Neptune](gremlin-api-reference.md)
+ [Mise en cache des résultats de requête dans Amazon Neptune Gremlin](gremlin-results-cache.md)
+ [Réalisation d'upserts efficaces avec les étapes Gremlin `mergeV()` et `mergeE()`](gremlin-efficient-upserts.md)
+ [Réalisation d'upserts Gremlin efficaces avec `fold()/coalesce()/unfold()`](gremlin-efficient-upserts-pre-3.6.md)
+ [Analyse de l'exécution des requêtes à l'aide de Gremlin `explain`](gremlin-explain.md)
+ [Utilisation de Gremlin avec le moteur de requêtes Neptune DFE](gremlin-with-dfe.md)

# Configuration de la console Gremlin pour se connecter à une instance de base de données Neptune
<a name="access-graph-gremlin-console"></a>

La console G705 vous permet d'expérimenter avec TinkerPop des graphes et des requêtes dans un environnement REPL (read-eval-print boucle).

## Installation de la console Gremlin et mode de connexion habituel
<a name="access-graph-gremlin-console-usual-connect"></a>

Vous pouvez utiliser la console Gremlin pour vous connecter à une base de données distante orientée graphe. La section suivante vous guide dans l’installation et la configuration de la console Gremlin pour une connexion à distance à une instance de base de données Neptune. Vous devez suivre ces instructions à partir d'une instance Amazon EC2 dans le même cloud privé virtuel (VPC) (VPC) que l'instance de base de données Neptune.

Pour obtenir de l'aide sur la connexion à Neptune avec SSL/TLS (obligatoire), consultez. [Configuration SSL/TLS](access-graph-gremlin-java.md#access-graph-gremlin-java-ssl)

**Note**  
Si l'[authentification IAM est activée](iam-auth-enable.md) sur votre cluster de bases de données Neptune, suivez les instructions décrites dans [Connexion aux bases de données Amazon Neptune à l'aide de l'authentification IAM avec la console Gremlin](iam-auth-connecting-gremlin-console.md) pour installer la console Gremlin plutôt que celles indiquées ici.

**Pour installer la console Gremlin et vous connecter à Neptune**

1. Les fichiers binaires de la console Gremlin nécessitent Java 8 ou Java 11. Ces instructions supposent l'utilisation de Java 11. Vous pouvez installer Java 11 sur une instance EC2 comme suit :
   + Si vous utilisez [Amazon Linux 2 (AL2)](https://aws.amazon.com/amazon-linux-2) :

     ```
     sudo amazon-linux-extras install java-openjdk11
     ```
   + Si vous utilisez [Amazon Linux 2023 (AL2023)](https://docs.aws.amazon.com/linux/al2023/ug/what-is-amazon-linux.html) :

     ```
     sudo yum install java-11-amazon-corretto-devel
     ```
   + Pour les autres distributions, utilisez l'instruction qui convient le mieux parmi les suivantes :

     ```
     sudo yum install java-11-openjdk-devel
     ```

     ou :

     ```
     sudo apt-get install openjdk-11-jdk
     ```

1. Entrez la commande suivante pour définir Java 8 en tant qu'environnement d'exécution par défaut sur votre instance EC2.

   ```
   sudo /usr/sbin/alternatives --config java
   ```

   Lorsque vous y êtes invité, saisissez le nombre correspondant à Java 11.

1. Téléchargez la version appropriée de la console Gremlin depuis le site Web d'Apache. Vous pouvez vérifier si votre version de [Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md) Neptune est prise en charge par votre version de Gremlin. Par exemple, si vous avez besoin de la version 3.7.2, vous pouvez télécharger la [console Gremlin](https://archive.apache.org/dist/tinkerpop/3.7.2/apache-tinkerpop-gremlin-console-3.7.2-bin.zip) depuis le site Web [Apache Tinkerpop](https://tinkerpop.apache.org/download.html) sur votre instance EC2 comme suit :

   ```
   wget https://archive.apache.org/dist/tinkerpop/3.7.2/apache-tinkerpop-gremlin-console-3.7.2-bin.zip
   ```

1. Décompressez le fichier zip Gremlin Console.

   ```
   unzip apache-tinkerpop-gremlin-console-3.7.2-bin.zip
   ```

1. Modifiez les répertoires du répertoire décompressé.

   ```
   cd apache-tinkerpop-gremlin-console-3.7.2
   ```

1. Dans le sous-répertoire `conf` du répertoire extrait, créez un fichier nommé `neptune-remote.yaml` avec le texte suivant. *your-neptune-endpoint*Remplacez-le par le nom d'hôte ou l'adresse IP de votre instance de base de données Neptune. Les crochets (`[ ]`) sont obligatoires.
**Note**  
Consultez la section [Connexion aux points de terminaison Amazon Neptune](feature-overview-endpoints.md) pour découvrir comment trouver le nom d'hôte de votre instance de base de données Neptune.

   ```
   hosts: [your-neptune-endpoint]
   port: 8182
   connectionPool: { enableSsl: true }
   serializer: { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1,
                 config: { serializeResultToString: true }}
   ```
**Note**  
 Les sérialiseurs ont été déplacés du `gremlin-driver` module vers le nouveau `gremlin-util` module dans la version 3.7.0. Le package est passé de org.apache.tinkerpop.gremlin.driver.ser à org.apache.tinkerpop.gremlin.util.ser. 

1. Dans un terminal, accédez au répertoire Gremlin Console (`apache-tinkerpop-gremlin-console-3.7.2`), puis entrez la commande suivante pour exécuter la console Gremlin.

   ```
   bin/gremlin.sh
   ```

   Vous devriez voir la sortie suivante :

   ```
            \,,,/
            (o o)
   -----oOOo-(3)-oOOo-----
   plugin activated: tinkerpop.server
   plugin activated: tinkerpop.utilities
   plugin activated: tinkerpop.tinkergraph
   gremlin>
   ```

   Vous êtes maintenant à l'invite `gremlin>`. Vous entrez les étapes restantes à cette invite.

1. À l'invite de commande `gremlin>`, saisissez le texte suivant pour vous connecter à l'instance de base de données Neptune.

   ```
   :remote connect tinkerpop.server conf/neptune-remote.yaml
   ```

1. À l'invite `gremlin>`, entrez ce qui suit pour passer en mode distant. Toutes les requêtes Gremlin sont alors envoyées à la connexion distante.

   ```
   :remote console
   ```

1. Saisissez la commande suivante pour envoyer une requête au graphe Gremlin.

   ```
   g.V().limit(1)
   ```

1. Lorsque vous avez terminé, saisissez la commande suivante pour quitter la console Gremlin.

   ```
   :exit
   ```

**Note**  
Utilisez un point-virgule (`;`) ou un caractère de saut de ligne (`\n`) pour séparer chaque instruction.   
Chaque traversée précédant la traversée finale doit se terminer par l'exécution de `next()`. Seules les données de la traversée finale sont renvoyées.

Pour plus d'informations sur l'implémentation Neptune de Gremlin, consultez [Conformité d'Amazon Neptune avec les normes Gremlin](access-graph-gremlin-differences.md).

# Autre mode de connexion à la console Gremlin
<a name="access-graph-gremlin-console-connect"></a>

**Inconvénients de l'approche de connexion habituelle**

La méthode la plus courante pour se connecter à la console Gremlin est expliquée ci-dessus et utilise des commandes comme celle-ci à l'invite `gremlin>` :

```
gremlin> :remote connect tinkerpop.server conf/(file name).yaml
gremlin> :remote console
```

Elle est opérationnelle et vous permet d'envoyer des requêtes à Neptune. Cependant, elle exclut le moteur de script Groovy, de sorte que Neptune traite toutes les requêtes comme si elles étaient entièrement écrites dans Gremlin. Par conséquent, les types de requête suivants échouent :

```
gremlin> 1 + 1
gremlin> x = g.V().count()
```

Le meilleur moyen d'utiliser une variable lorsque vous êtes connecté de cette façon consiste à utiliser la variable `result` gérée par la console et d'envoyer la requête en utilisant `:>`, comme ceci :

```
gremlin> :remote console
==>All scripts will now be evaluated locally - type ':remote console' to return to remote mode for Gremlin Server - [krl-1-cluster.cluster-ro-cm9t6tfwbtsr.us-east-1.neptune.amazonaws.com/172.31.19.217:8182]
gremlin> :> g.V().count()
==>4249

gremlin> println(result)
[result{object=4249 class=java.lang.Long}]

gremlin> println(result['object'])
[4249]
```

 

**Autre mode de connexion**

Vous pouvez également vous connecter à la console Gremlin d'une autre manière, que vous trouverez peut-être plus agréable, comme ceci :

```
gremlin> g = traversal().withRemote('conf/neptune.properties')
```

`neptune.properties` prend ici la forme suivante :

```
gremlin.remote.remoteConnectionClass=org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection
gremlin.remote.driver.clusterFile=conf/my-cluster.yaml
gremlin.remote.driver.sourceName=g
```

Le fichier `my-cluster.yaml` doit ressembler à ceci :

```
hosts: [my-cluster-abcdefghijk.us-east-1.neptune.amazonaws.com]
port: 8182
serializer: { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1,
              config: { serializeResultToString: false } }
connectionPool: { enableSsl: true }
```

**Note**  
 Les sérialiseurs ont été déplacés du `gremlin-driver` module vers le nouveau `gremlin-util` module dans la version 3.7.0. Le package est passé de org.apache.tinkerpop.gremlin.driver.ser à org.apache.tinkerpop.gremlin.util.ser. 

En configurant ainsi la connexion à la console Gremlin, vous pouvez effectuer avec succès les types de requêtes suivants :

```
gremlin> 1+1
==>2

gremlin> x=g.V().count().next()
==>4249

gremlin> println("The answer was ${x}")
The answer was 4249
```

Pour éviter d'afficher le résultat, procédez comme suit :

```
gremlin> x=g.V().count().next();[]
gremlin> println(x)
4249
```

Toutes les méthodes habituelles d'interrogation (sans l'étape terminale) continuent de fonctionner. Par exemple :

```
gremlin> g.V().count()
==>4249
```

Vous pouvez même utiliser l'étape [https://tinkerpop.apache.org/docs/current/reference/#io-step](https://tinkerpop.apache.org/docs/current/reference/#io-step) pour charger un fichier avec ce type de connexion.

## Authentification IAM
<a name="access-graph-gremlin-console-iam"></a>

Neptune prend en charge l'[authentification IAM](iam-auth-enable.md) pour contrôler l'accès à votre cluster de base de données. Si l'authentification IAM est activée, vous devez utiliser la signature Signature version 4 pour authentifier vos demandes. Pour obtenir des instructions détaillées et des exemples de code pour la connexion depuis la console Gremlin, consultez[Connexion aux bases de données Amazon Neptune à l'aide de l'authentification IAM avec la console Gremlin](iam-auth-connecting-gremlin-console.md).

# Utilisation du point de terminaison HTTP REST pour se connecter à une instance de base de données Neptune
<a name="access-graph-gremlin-rest"></a>

Amazon Neptune fournit un point de terminaison HTTP pour les requêtes Gremlin. L'interface REST est compatible avec n'importe quelle version Gremlin de votre cluster de bases de données (consultez la [page de mise à jour](engine-releases.md) correspondant à la version de moteur Neptune que vous exécutez pour déterminer la version Gremlin prise en charge).

**Note**  
Comme indiqué dans [Chiffrement des connexions à votre base de données Amazon Neptune avec SSL/HTTPS](security-ssl.md), vous devez désormais vous connecter via HTTPS au lieu de HTTP dans Neptune. En outre, Neptune ne prend actuellement pas en charge le HTTP/2 pour les requêtes d'API REST. Les clients doivent utiliser HTTP/1.1 lorsqu'ils se connectent aux points de terminaison.

Les instructions suivantes vous guident à travers la connexion au point de terminaison Gremlin à l'aide de la commande `curl` et de HTTPS. Vous devez suivre ces instructions à partir d'une instance Amazon EC2 dans le même cloud privé virtuel (VPC) (VPC) que l'instance de base de données Neptune.

Le point de terminaison HTTPS pour les requêtes Gremlin dans une instance de base de données Neptune est `https://your-neptune-endpoint:port/gremlin`.

**Note**  
Pour découvrir comment trouver le nom d'hôte de l'instance de base de données Neptune, consultez la section [Connexion aux points de terminaison Amazon Neptune](feature-overview-endpoints.md).

## Pour se connecter à Neptune à l'aide du point de terminaison HTTP REST
<a name="access-graph-gremlin-rest-connect"></a>

L'exemple suivant utilise **curl** pour soumettre une requête Gremlin via HTTP **POST**. La requête est soumise au format JSON dans le corps de la publication en tant que propriété `gremlin`.

```
curl -X POST -d '{"gremlin":"g.V().limit(1)"}' https://your-neptune-endpoint:port/gremlin
```

L'exemple précédent renvoie le premier sommet du graphe en utilisant la traversée `g.V().limit(1)`. Pour interroger autre chose, remplacez cette traversée par une autre traversée Gremlin.

**Important**  
Par défaut, le point de terminaison REST renvoie tous les résultats dans un seul ensemble de résultats JSON. Si cet ensemble de résultats est trop volumineux, une exception `OutOfMemoryError` peut être générée dans l'instance de base de données Neptune.  
Pour éviter cette exception, activez les réponses segmentées (résultats renvoyés sous la forme d'une série de réponses distinctes). Consultez [Utilisation d'en-têtes de suivi HTTP facultatifs pour activer les réponses Gremlin en plusieurs parties](access-graph-gremlin-rest-trailing-headers.md).

Bien que les demandes HTTP **POST** soient recommandées pour envoyer des requêtes Gremlin, il est également possible d'utiliser des demandes HTTP **GET** :

```
curl -G "https://your-neptune-endpoint:port?gremlin=g.V().count()"
```

**Note**  
Neptune ne prend pas en charge la propriété `bindings`.

# Utilisation d'en-têtes de suivi HTTP facultatifs pour activer les réponses Gremlin en plusieurs parties
<a name="access-graph-gremlin-rest-trailing-headers"></a>

Par défaut, la réponse HTTP aux requêtes Gremlin est renvoyée dans un seul ensemble de résultats JSON. Un ensemble de résultats très volumineux peut générér une exception `OutOfMemoryError` dans l'instance de base de données.

Vous pouvez toutefois activer les *réponses segmentées* (réponses renvoyées en plusieurs parties distinctes). Pour ce faire, incluez un en-tête « trailer » (`te: trailers`) d'encodage de transfert (TE) dans la demande. Consultez la [page MDN (sur les en-têtes de demande TE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/TE)) pour plus d'informations sur ces en-têtes.

Lorsqu'une réponse est renvoyée en plusieurs parties, il peut être difficile de diagnostiquer un problème qui survient après la réception de la première partie, car la première partie arrive avec le code de statut HTTP `200` (OK). En cas d'échec ultérieur, le corps du message contient généralement une réponse corrompue, à la fin de laquelle Neptune ajoute un message d'erreur.

Pour faciliter la détection et le diagnostic de ce type d'échec, Neptune inclut également deux nouveaux champs d'en-tête dans les en-têtes suivants de chaque segment de réponse :
+ `X-Neptune-Status` : contient le code de réponse suivi d'un nom court. Par exemple, en cas de réussite, l'en-tête final serait : `X-Neptune-Status: 200 OK`. En cas d'échec, le code de réponse est l'un des [codes d'erreur du moteur Neptune](errors-engine-codes.md), tel que `X-Neptune-Status: 500 TimeLimitExceededException`.
+ `X-Neptune-Detail` : est vide pour les demandes qui ont abouti. En cas d'erreur, il contient le message d'erreur JSON. Étant donné que seuls les caractères ASCII sont autorisés dans les valeurs d'en-tête HTTP, la chaîne JSON est encodée en URL.

**Note**  
Neptune ne prend actuellement pas en charge la compression `gzip` des réponses segmentées. Si le client demande à la fois un encodage et une compression segmentés, Neptune ignore la compression.

# Clients Gremlin basés sur Java à utiliser avec Amazon Neptune
<a name="access-graph-gremlin-client"></a>

[Vous pouvez utiliser l'un des deux clients G705 open source basés sur Java avec Amazon Neptune : le client [Apache TinkerPop Java G705 ou le client G705](https://search.maven.org/artifact/org.apache.tinkerpop/gremlin-driver) pour Amazon Neptune.](https://search.maven.org/artifact/software.amazon.neptune/gremlin-client)

## Client Apache TinkerPop Java Garmlin
<a name="access-graph-gremlin-java-driver"></a>

Le [pilote Apache TinkerPop Java gremlin](https://tinkerpop.apache.org/docs/current/reference/#gremlin-java) est le client Gremlin standard et officiel qui fonctionne avec n'importe quelle TinkerPop base de données de graphes compatible. Utilisez ce client lorsque vous avez besoin d'une compatibilité maximale avec l'ensemble de l'espace de TinkerPop développement, lorsque vous travaillez avec plusieurs systèmes de base de données de graphes ou lorsque vous n'avez pas besoin des fonctionnalités avancées de gestion des clusters et d'équilibrage de charge spécifiques à Neptune. Ce client convient également aux applications simples qui se connectent à une seule instance Neptune ou lorsque vous préférez gérer l'équilibrage de charge au niveau de l'infrastructure plutôt qu'au sein du client.

**Important**  
Le choix de la bonne version du pilote Apache TinkerPop Gremlin est essentiel pour garantir la compatibilité avec la version de votre moteur Neptune. L'utilisation d'une version incompatible peut entraîner des échecs de connexion ou un comportement inattendu. Pour obtenir des informations détaillées sur la compatibilité des versions, consultez[Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md).

**Note**  
Le tableau qui vous aide à déterminer la TinkerPop version correcte d'Apache à utiliser avec Neptune a été déplacé vers. [Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md) Ce tableau se trouvait auparavant sur cette page depuis de nombreuses années et est désormais plus centralisé à titre de référence pour tous les langages de programmation pris TinkerPop en charge.

## Client Java Gremlin pour Amazon Neptune
<a name="access-graph-neptune-gremlin-client"></a>

Le client Gremlin pour Amazon Neptune est [un client Gremlin open source basé sur Java](https://github.com/aws/neptune-gremlin-client) qui remplace directement le client Java standard. TinkerPop 

Le client Gremlin Neptune est optimisé pour les clusters Neptune. Il vous permet de gérer la distribution du trafic entre plusieurs instances d'un cluster et s'adapte aux modifications de la topologie du cluster lorsque vous ajoutez ou supprimez un réplica. Vous pouvez même configurer le client pour distribuer les demandes sur un sous-ensemble d'instances du cluster, en fonction du rôle, du type d'instance, de la zone de disponibilité (AZ) ou des balises associées aux instances.

La [dernière version du client Java Gremlin Neptune](https://search.maven.org/artifact/software.amazon.neptune/gremlin-client) est disponible sur Maven Central.

Pour plus d'informations sur le client Java Gremlin Neptune, consultez [ce billet de blog](https://aws.amazon.com/blogs/database/load-balance-graph-queries-using-the-amazon-neptune-gremlin-client/). Pour des exemples de code et des démos, consultez le [ GitHub projet du client](https://github.com/aws/neptune-gremlin-client).

Lorsque vous choisissez la version du client Neptune G705, vous devez prendre en compte la TinkerPop version sous-jacente par rapport à la version de votre moteur Neptune. Reportez-vous au tableau de compatibilité sur [Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md) pour déterminer la TinkerPop version appropriée pour votre moteur Neptune, puis utilisez le tableau suivant pour sélectionner la version du client Neptune Gremlin appropriée :


**Compatibilité des versions du client Neptune Garmlin**  

| Version du client Neptune Garmlin | TinkerPop version | 
| --- | --- | 
| 3.x | 3.7.x (AWS SDK pour Java 2.x/1.x) | 
| 2.1.x | 3.7.x (AWS SDK pour Java 1.x) | 
| 2.0.x | 3,6. x | 
| 1.12 | 3.5.x | 

# Utilisation du client Java pour se connecter à une instance de base de données Neptune
<a name="access-graph-gremlin-java"></a>

La section suivante explique comment exécuter un exemple Java complet qui se connecte à une instance de base de données Neptune et effectue une traversée de G705 à l'aide du client Apache G705. TinkerPop

Vous devez suivre ces instructions à partir d'une instance Amazon EC2 située dans le même cloud privé virtuel (VPC) (VPC) que l'instance de base de données Neptune.

**Pour se connecter à Neptune à l'aide de Java**

1. Installez Apache Maven sur votre instance EC2. Si vous utilisez Amazon Linux 2023 (de préférence), utilisez :

   ```
   sudo dnf update -y
   sudo dnf install maven -y
   ```

   Si vous utilisez Amazon Linux 2, téléchargez le dernier fichier binaire [sur https://maven.apache.org/download.cgi :](https://maven.apache.org/download.cgi:)

   ```
   sudo yum remove maven -y
   wget https://dlcdn.apache.org/maven/maven-3/ <version>/binaries/apache-maven-<version>-bin.tar.gz
   sudo tar -xzf apache-maven-<version>-bin.tar.gz -C /opt/
   sudo ln -sf /opt/apache-maven-<version> /opt/maven
   echo 'export MAVEN_HOME=/opt/maven' >> ~/.bashrc
   echo 'export PATH=$MAVEN_HOME/bin:$PATH' >> ~/.bashrc
   source ~/.bashrc
   ```

1. **Installez Java.** Les bibliothèques Gremlin nécessitent Java 8 ou 11. Vous pouvez installer Java 11 comme suit :
   + Si vous utilisez [Amazon Linux 2 (AL2)](https://aws.amazon.com/amazon-linux-2) :

     ```
     sudo amazon-linux-extras install java-openjdk11
     ```
   + Si vous utilisez [Amazon Linux 2023 (AL2023)](https://docs.aws.amazon.com/linux/al2023/ug/what-is-amazon-linux.html) :

     ```
     sudo yum install java-11-amazon-corretto-devel
     ```
   + Pour les autres distributions, utilisez l'instruction qui convient le mieux parmi les suivantes :

     ```
     sudo yum install java-11-openjdk-devel
     ```

     ou :

     ```
     sudo apt-get install openjdk-11-jdk
     ```

1. **Définissez Java 11 comme environnement d'exécution par défaut sur votre instance EC2 :** entrez ce qui suit pour définir Java 8 comme environnement d'exécution par défaut sur l'instance EC2 :

   ```
   sudo /usr/sbin/alternatives --config java
   ```

   Lorsque vous y êtes invité, saisissez le nombre correspondant à Java 11.

1. **Créez un répertoire appelé `gremlinjava` :**

   ```
   mkdir gremlinjava
   cd gremlinjava
   ```

1.  Dans le répertoire `gremlinjava`, créez un fichier `pom.xml`, puis ouvrez-le dans un éditeur de texte:

   ```
   nano pom.xml
   ```

1. Copiez ce qui suit dans le fichier `pom.xml` et enregistrez-le:

   ```
   <project xmlns="https://maven.apache.org/POM/4.0.0"
            xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
     <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.amazonaws</groupId>
     <artifactId>GremlinExample</artifactId>
     <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>GremlinExample</name>
     <url>https://maven.apache.org</url>
     <dependencies>
       <dependency>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>gremlin-driver</artifactId>
         <version>3.7.2</version>
       </dependency>
       <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-jdk14</artifactId>
         <version>1.7.25</version>
       </dependency>
     </dependencies>
     <build>
       <plugins>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>2.5.1</version>
           <configuration>
             <source>11</source>
             <target>11</target>
           </configuration>
         </plugin>
           <plugin>
             <groupId>org.codehaus.mojo</groupId>
             <artifactId>exec-maven-plugin</artifactId>
             <version>1.3</version>
             <configuration>
               <executable>java</executable>
               <arguments>
                 <argument>-classpath</argument>
                 <classpath/>
                 <argument>com.amazonaws.App</argument>
               </arguments>
               <mainClass>com.amazonaws.App</mainClass>
               <complianceLevel>1.11</complianceLevel>
               <killAfter>-1</killAfter>
             </configuration>
           </plugin>
       </plugins>
     </build>
   </project>
   ```
**Note**  
Si vous modifiez un projet Maven existant, la dépendance obligatoire est mise en évidence dans le code précédent.

1. Créez des sous-répertoires pour l'exemple de code source (`src/main/java/com/amazonaws/`) en saisissant ce qui suit sur la ligne de commande :

   ```
   mkdir -p src/main/java/com/amazonaws/
   ```

1. Dans le répertoire `src/main/java/com/amazonaws/`, créez un fichier `App.java`, puis ouvrez-le dans un éditeur de texte.

   ```
   nano src/main/java/com/amazonaws/App.java
   ```

1. Copiez ce qui suit dans le fichier `App.java`. Remplacez *your-neptune-endpoint* par l'adresse de votre instance de base de données Neptune. N’incluez *pas* le préfixe `https://` dans la méthode `addContactPoint`.
**Note**  
Pour découvrir comment trouver le nom d'hôte de l'instance de base de données Neptune, consultez la section [Connexion aux points de terminaison Amazon Neptune](feature-overview-endpoints.md).

   ```
   package com.amazonaws;
   import org.apache.tinkerpop.gremlin.driver.Cluster;
   import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
   import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
   import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
   import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
   import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
   import org.apache.tinkerpop.gremlin.structure.T;
   
   public class App
   {
     public static void main( String[] args )
     {
       Cluster.Builder builder = Cluster.build();
       builder.addContactPoint("your-neptune-endpoint");
       builder.port(8182);
       builder.enableSsl(true);
   
       Cluster cluster = builder.create();
   
       GraphTraversalSource g = traversal().withRemote(DriverRemoteConnection.using(cluster));
   
       // Add a vertex.
       // Note that a Gremlin terminal step, e.g. iterate(), is required to make a request to the remote server.
       // The full list of Gremlin terminal steps is at https://tinkerpop.apache.org/docs/current/reference/#terminal-steps
       g.addV("Person").property("Name", "Justin").iterate();
   
       // Add a vertex with a user-supplied ID.
       g.addV("Custom Label").property(T.id, "CustomId1").property("name", "Custom id vertex 1").iterate();
       g.addV("Custom Label").property(T.id, "CustomId2").property("name", "Custom id vertex 2").iterate();
   
       g.addE("Edge Label").from(__.V("CustomId1")).to(__.V("CustomId2")).iterate();
   
       // This gets the vertices, only.
       GraphTraversal t = g.V().limit(3).elementMap();
   
       t.forEachRemaining(
         e ->  System.out.println(t.toList())
       );
   
       cluster.close();
     }
   }
   ```

   Pour obtenir de l'aide sur la connexion à Neptune avec SSL/TLS (obligatoire), consultez. [Configuration SSL/TLS](#access-graph-gremlin-java-ssl)

1. Compilez et exécutez l'exemple à l'aide de la commande Maven suivante :

   ```
   mvn compile exec:exec
   ```

L'exemple précédent renvoie une carte de la clé et les valeurs de chaque propriété pour les deux premiers vertex du graphe à l'aide de la traversée `g.V().limit(3).elementMap()`. Pour interroger quelque chose d'autre, remplacez la traversée par une autre traversée Gremlin avec l'une des méthodes de fin appropriées.

**Note**  
La partie finale de la requête Gremlin, `.toList()`, est obligatoire pour soumettre la traversée au serveur à des fins d'évaluation. Si vous n'incluez pas cette méthode ou une autre méthode équivalente, la requête ne sera pas soumise à l'instance de base de données Neptune.  
Vous devez également ajouter une terminaison appropriée lorsque vous ajoutez un sommet ou une arête, comme lorsque vous utilisez l'étape `addV( )`.

Les méthodes suivantes soumettent la requête à l'instance de base de données Neptune :
+ `toList()`
+ `toSet()`
+ `next()`
+ `nextTraverser()`
+ `iterate()`

## Configuration SSL/TLS pour le client Java Gremlin
<a name="access-graph-gremlin-java-ssl"></a>

Neptune doit SSL/TLS être activé par défaut. Généralement, si le pilote Java est configuré avec `enableSsl(true)`, il peut se connecter à Neptune sans avoir à configurer `trustStore()` ou `keyStore()` avec une copie locale d'un certificat.

Toutefois, si l'instance à laquelle vous vous connectez ne dispose pas d'une connexion Internet permettant de vérifier un certificat public ou si le certificat que vous utilisez n'est pas public, vous pouvez suivre les étapes ci-dessous pour configurer une copie du certificat local :

**Configuration d'une copie du certificat local pour activer le protocole SSL/TLS**

1. Téléchargez et installez [keytool](https://docs.oracle.com/javase/9/tools/keytool.htm#JSWOR-GUID-5990A2E4-78E3-47B7-AE75-6D1826259549) depuis Oracle. Cela facilitera grandement la configuration du magasin de clés local.

1. Téléchargez le certificat CA `SFSRootCAG2.pem` (le kit SDK Java Gremlin a besoin d'un certificat pour vérifier le certificat à distance).

   ```
   wget https://www.amazontrust.com/repository/SFSRootCAG2.pem
   ```

1. Créez un magasin de clés au format JKS ou PKCS12 au format. Cet exemple utilise JKS. Répondez aux questions qui suivent à l'invite. Le mot de passe que vous créez ici sera nécessaire ultérieurement :

   ```
   keytool -genkey -alias (host name) -keyalg RSA -keystore server.jks
   ```

1. Importez le fichier `SFSRootCAG2.pem` que vous avez téléchargé dans le magasin de clés que vous venez de créer :

   ```
   keytool -import -keystore server.jks -file .pem
   ```

1. Configurez l'objet `Cluster` par programmation :

   ```
   Cluster cluster = Cluster.build("(your neptune endpoint)")
                            .port(8182)
                            .enableSSL(true)
                            .keyStore(‘server.jks’)
                            .keyStorePassword("(the password from step 2)")
                            .create();
   ```

   Vous pouvez faire la même chose dans un fichier de configuration si vous le souhaitez, comme vous pourriez le faire avec la console Gremlin :

   ```
   hosts: [(your neptune endpoint)]
   port: 8182
   connectionPool: { enableSsl: true, keyStore: server.jks, keyStorePassword: (the password from step 2) }
   serializer: { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
   ```

## Authentification IAM
<a name="access-graph-gremlin-java-iam"></a>

Neptune prend en charge l'[authentification IAM](iam-auth-enable.md) pour contrôler l'accès à votre cluster de base de données. Si l'authentification IAM est activée, vous devez utiliser la signature Signature version 4 pour authentifier vos demandes. Pour obtenir des instructions détaillées et des exemples de code pour la connexion à partir d'un client Java, consultez[Connexion aux bases de données Amazon Neptune à l'aide d'IAM avec Gkremlin Java](iam-auth-connecting-gremlin-java.md).

# Exemple Java de connexion à une instance de base de données Neptune avec une logique de reconnexion
<a name="access-graph-gremlin-java-reconnect-example"></a>

L'exemple Java suivant montre comment se connecter au client Gremlin à l'aide d'une logique de reconnexion afin d'assurer la reprise après une déconnexion inattendue.

Il présente les dépendances suivantes :

```
<dependency>
    <groupId>org.apache.tinkerpop</groupId>
    <artifactId>gremlin-driver</artifactId>
    <version>${gremlin.version}</version>
</dependency>

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>amazon-neptune-sigv4-signer</artifactId>
    <version>${sig4.signer.version}</version>
</dependency>

<dependency>
    <groupId>com.evanlennick</groupId>
    <artifactId>retry4j</artifactId>
    <version>0.15.0</version>
</dependency>
```

Voici l'exemple de code :

**Important**  
 Le `CallExecutor` de Retry4j n'est peut-être pas thread-safe. Envisagez de demander à chaque thread d'utiliser sa propre `CallExecutor` instance ou d'utiliser une bibliothèque de nouvelles tentatives différente. 

**Note**  
 L'exemple suivant a été mis à jour pour inclure l'utilisation de RequestInterceptor (). Cela a été ajouté dans la version TinkerPop 3.6.6. Avant la TinkerPop version 3.6.6, l'exemple de code utilisait HandshakeInterceptor (), qui était obsolète avec cette version. 

```
public static void main(String args[]) {
  boolean useIam = true;

  // Create Gremlin cluster and traversal source
  Cluster.Builder builder = Cluster.build()
         .addContactPoint(System.getenv("neptuneEndpoint"))
         .port(Integer.parseInt(System.getenv("neptunePort")))
         .enableSsl(true)
         .minConnectionPoolSize(1)
         .maxConnectionPoolSize(1)
         .serializer(Serializers.GRAPHBINARY_V1D0)
         .reconnectInterval(2000);

  if (useIam) {
      builder.requestInterceptor( r -> {
         try {
            NeptuneNettyHttpSigV4Signer sigV4Signer =
                        new NeptuneNettyHttpSigV4Signer("(your region)", new DefaultAWSCredentialsProviderChain());
            sigV4Signer.signRequest(r);
         } catch (NeptuneSigV4SignerException e) {
            throw new RuntimeException("Exception occurred while signing the request", e);
         }
         return r;
      });
   }

  Cluster cluster = builder.create();

  GraphTraversalSource g = AnonymousTraversalSource
      .traversal()
      .withRemote(DriverRemoteConnection.using(cluster));

  // Configure retries
  RetryConfig retryConfig = new RetryConfigBuilder()
      .retryOnCustomExceptionLogic(getRetryLogic())
      .withDelayBetweenTries(1000, ChronoUnit.MILLIS)
      .withMaxNumberOfTries(5)
      .withFixedBackoff()
      .build();

  @SuppressWarnings("unchecked")
  CallExecutor<Object> retryExecutor = new CallExecutorBuilder<Object>()
      .config(retryConfig)
      .build();

  // Do lots of queries
  for (int i = 0; i < 100; i++){
    String id = String.valueOf(i);

    @SuppressWarnings("unchecked")
    Callable<Object> query = () -> g.V(id)
        .fold()
        .coalesce(
            unfold(),
            addV("Person").property(T.id, id))
        .id().next();

    // Retry query
    // If there are connection failures, the Java Gremlin client will automatically
    // attempt to reconnect in the background, so all we have to do is wait and retry.
    Status<Object> status = retryExecutor.execute(query);

    System.out.println(status.getResult().toString());
  }

  cluster.close();
}

private static Function<Exception, Boolean> getRetryLogic() {

  return e -> {

    Class<? extends Exception> exceptionClass = e.getClass();

    StringWriter stringWriter = new StringWriter();
    String message = stringWriter.toString();


    if (RemoteConnectionException.class.isAssignableFrom(exceptionClass)){
      System.out.println("Retrying because RemoteConnectionException");
      return true;
    }

    // Check for connection issues
    if (message.contains("Timed out while waiting for an available host") ||
        message.contains("Timed-out") && message.contains("waiting for connection on Host") ||
        message.contains("Connection to server is no longer active") ||
        message.contains("Connection reset by peer") ||
        message.contains("SSLEngine closed already") ||
        message.contains("Pool is shutdown") ||
        message.contains("ExtendedClosedChannelException") ||
        message.contains("Broken pipe") ||
        message.contains(System.getenv("neptuneEndpoint")))
    {
      System.out.println("Retrying because connection issue");
      return true;
    };

    // Concurrent writes can sometimes trigger a ConcurrentModificationException.
    // In these circumstances you may want to backoff and retry.
    if (message.contains("ConcurrentModificationException")) {
      System.out.println("Retrying because ConcurrentModificationException");
      return true;
    }

    // If the primary fails over to a new instance, existing connections to the old primary will
    // throw a ReadOnlyViolationException. You may want to back and retry.
    if (message.contains("ReadOnlyViolationException")) {
      System.out.println("Retrying because ReadOnlyViolationException");
      return true;
    }

    System.out.println("Not a retriable error");
    return false;
  };
}
```

# Utilisation de Python pour se connecter à une instance de base de données Neptune
<a name="access-graph-gremlin-python"></a>

**Important**  
Le choix de la bonne version du pilote TinkerPop Apache G705 est essentiel pour garantir la compatibilité avec la version de votre moteur Neptune. L'utilisation d'une version incompatible peut entraîner des échecs de connexion ou un comportement inattendu. Pour obtenir des informations détaillées sur la compatibilité des versions, consultez[Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md).

La section suivante vous accompagne dans l'exécution d'un exemple Python qui se connecte à une instance de base de données Amazon Neptune et effectue une traversée Gremlin.

Vous devez suivre ces instructions à partir d'une instance Amazon EC2 dans le même cloud privé virtuel (VPC) (VPC) que l'instance de base de données Neptune.

Avant de commencer, vous devez exécuter les actions suivantes :
+ Téléchargez et installez Python 3.6 ou version ultérieure depuis le [site web Python.org](https://www.python.org/downloads/).
+ Vérifiez que vous avez installé **pip**. Si vous n'avez pas **pip** ou que vous n'en êtes pas certain, voir [Do I need to install pip? (Dois-je installer pip?](https://pip.pypa.io/en/stable/installing/#do-i-need-to-install-pip) dans la documentation **pip**.
+ Si votre installation Python n'est pas déjà définie, téléchargez `futures` comme suit : `pip install futures`



**Pour se connecter à Neptune à l'aide de Python**

1. Entrez ce qui suit pour installer le package `gremlinpython` :

   ```
   pip install --user gremlinpython
   ```

1. Créez un fichier nommé `gremlinexample.py` et ouvrez-le dans un éditeur de texte.

1. Copiez ce qui suit dans le fichier `gremlinexample.py`. Remplacez *your-neptune-endpoint* par l'adresse de votre cluster de base de données Neptune et *your-neptune-port* par le port de votre cluster de base de données Neptune (par défaut : 8182). 

   Consultez la section [Connexion aux points de terminaison Amazon Neptune](feature-overview-endpoints.md) pour découvrir comment trouver l'adresse de votre instance de base de données Neptune.

    L'exemple ci-dessous montre comment se connecter à Garmlin Python. 

   ```
   import boto3
   import os
   from botocore.auth import SigV4Auth
   from botocore.awsrequest import AWSRequest
   from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
   from gremlin_python.process.anonymous_traversal import traversal
   
   database_url = "wss://your-neptune-endpoint:your-neptune-port/gremlin"
   
   remoteConn = DriverRemoteConnection(database_url, "g")
   
   g = traversal().withRemote(remoteConn)
   
   print(g.inject(1).toList())
   remoteConn.close()
   ```

1. Pour exécuter l'exemple, entrez la commande suivante :

   ```
   python gremlinexample.py
   ```

   La requête Gremlin à la fin de cet exemple renvoie les vertex (`g.V().limit(2)`) dans une liste. Cette liste est ensuite imprimée avec la fonction standard Python `print`.
**Note**  
La partie finale de la requête Gremlin, `toList()`, est obligatoire pour soumettre la traversée au serveur à des fins d'évaluation. Si vous n'incluez pas cette méthode ou une autre méthode équivalente, la requête ne sera pas soumise à l'instance de base de données Neptune.

   Les méthodes suivantes soumettent la requête à l'instance de base de données Neptune :
   + `toList()`
   + `toSet()`
   + `next()`
   + `nextTraverser()`
   + `iterate()`

   

   L'exemple précédent renvoie les deux premier vertex du graphe en utilisant la traversée `g.V().limit(2).toList()`. Pour interroger quelque chose d'autre, remplacez la traversée par une autre traversée Gremlin avec l'une des méthodes de fin appropriées.

## Authentification IAM
<a name="access-graph-gremlin-python-iam"></a>

Neptune prend en charge l'[authentification IAM](iam-auth-enable.md) pour contrôler l'accès à votre cluster de base de données. Si l'authentification IAM est activée, vous devez utiliser la signature Signature version 4 pour authentifier vos demandes. Pour obtenir des instructions détaillées et des exemples de code pour la connexion à partir d'un client Python, consultez[Connexion aux bases de données Amazon Neptune à l'aide de l'authentification IAM avec Gremlin Python](gremlin-python-iam-auth.md).

# Utilisation de .NET pour se connecter à une instance de base de données Neptune
<a name="access-graph-gremlin-dotnet"></a>

**Important**  
Le choix de la bonne version du pilote TinkerPop Apache G705 est essentiel pour garantir la compatibilité avec la version de votre moteur Neptune. L'utilisation d'une version incompatible peut entraîner des échecs de connexion ou un comportement inattendu. Pour obtenir des informations détaillées sur la compatibilité des versions, consultez[Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md).

La section suivante contient un exemple de code écrit en C\$1 qui se connecte à une instance de base de données Neptune et effectue une traversée Gremlin.

Les connexions à Amazon Neptune doivent provenir d'une instance Amazon EC2 située dans le même cloud privé virtuel que votre instance de base de données Neptune. Cet exemple de code a été testé sur une instance Amazon EC2 exécutant Ubuntu.

Avant de commencer, vous devez exécuter les actions suivantes :
+ Installez .NET sur l'instance Amazon EC2. Pour obtenir des instructions sur la façon d'installer .NET sur plusieurs systèmes d'exploitation, notamment Windows, Linux et macOS, consultez [Mise en route avec .NET](https://www.microsoft.com/net/learn/get-started/).
+ Installez Gremlin.NET en exécutant `dotnet add package gremlin.net` pour votre package. Pour plus d'informations, consultez [Gremlin.net](https://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet) dans la documentation. TinkerPop 



**Pour se connecter à Neptune à l'aide de Gremlin.NET**

1. Crée un projet .NET.

   ```
   dotnet new console -o gremlinExample
   ```

1. Modifiez les répertoires vers le nouveau répertoire de projet.

   ```
   cd gremlinExample
   ```

1. Copiez ce qui suit dans le fichier `Program.cs`. Remplacez *your-neptune-endpoint* par l'adresse de votre instance de base de données Neptune.

   Consultez la section [Connexion aux points de terminaison Amazon Neptune](feature-overview-endpoints.md) pour découvrir comment trouver l'adresse de votre instance de base de données Neptune.

   ```
   using System;
   using System.Threading.Tasks;
   using System.Collections.Generic;
   using Gremlin.Net;
   using Gremlin.Net.Driver;
   using Gremlin.Net.Driver.Remote;
   using Gremlin.Net.Structure;
   using static Gremlin.Net.Process.Traversal.AnonymousTraversalSource;
   namespace gremlinExample
   {
     class Program
     {
       static void Main(string[] args)
       {
         try
         {
           var endpoint = "your-neptune-endpoint";
           // This uses the default Neptune and Gremlin port, 8182
           var gremlinServer = new GremlinServer(endpoint, 8182, enableSsl: true );
           var gremlinClient = new GremlinClient(gremlinServer);
           var remoteConnection = new DriverRemoteConnection(gremlinClient, "g");
           var g = Traversal().WithRemote(remoteConnection);
           g.AddV("Person").Property("Name", "Justin").Iterate();
           g.AddV("Custom Label").Property("name", "Custom id vertex 1").Iterate();
           g.AddV("Custom Label").Property("name", "Custom id vertex 2").Iterate();
           var output = g.V().Limit<Vertex>(3).ToList();
           foreach(var item in output) {
               Console.WriteLine(item);
           }
         }
         catch (Exception e)
         {
             Console.WriteLine("{0}", e);
         }
       }
     }
   }
   ```

1. Pour exécuter l'exemple, entrez la commande suivante :

   ```
   dotnet run
   ```

   La requête Gremlin à la fin de cet exemple renvoie le nombre d'un seul vertex à des fins de test. Elle est ensuite imprimée sur la console.
**Note**  
La partie finale de la requête Gremlin, `Next()`, est obligatoire pour soumettre la traversée au serveur à des fins d'évaluation. Si vous n'incluez pas cette méthode ou une autre méthode équivalente, la requête ne sera pas soumise à l'instance de base de données Neptune.

   Les méthodes suivantes soumettent la requête à l'instance de base de données Neptune :
   + `ToList()`
   + `ToSet()`
   + `Next()`
   + `NextTraverser()`
   + `Iterate()`

   Utilisez `Next()` si vous avez besoin que les résultats de la requête soient sérialisés et renvoyés, ou `Iterate()` dans le cas contraire.

   L'exemple précédent renvoie une liste à l'aide de la traversée `g.V().Limit(3).ToList()`. Pour interroger quelque chose d'autre, remplacez la traversée par une autre traversée Gremlin avec l'une des méthodes de fin appropriées.

## Authentification IAM
<a name="access-graph-gremlin-dotnet-iam"></a>

Neptune prend en charge l'[authentification IAM](iam-auth-enable.md) pour contrôler l'accès à votre cluster de base de données. Si l'authentification IAM est activée, vous devez utiliser la signature Signature version 4 pour authentifier vos demandes. Pour obtenir des instructions détaillées et des exemples de code pour la connexion à partir d'un client .NET, consultez[Connexion aux bases de données Amazon Neptune à l'aide de l'authentification IAM avec Gremlin .NET](gremlin-dotnet-iam-auth.md).

# Utilisation de Node.js pour se connecter à une instance de base de données Neptune
<a name="access-graph-gremlin-node-js"></a>

**Important**  
Le choix de la bonne version du pilote TinkerPop Apache G705 est essentiel pour garantir la compatibilité avec la version de votre moteur Neptune. L'utilisation d'une version incompatible peut entraîner des échecs de connexion ou un comportement inattendu. Pour obtenir des informations détaillées sur la compatibilité des versions, consultez[Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md).

La section suivante vous accompagne dans l'exécution d'un exemple Node.js qui se connecte à une instance de base de données Amazon Neptune et effectue une traversée Gremlin.

Vous devez suivre ces instructions à partir d'une instance Amazon EC2 dans le même cloud privé virtuel (VPC) (VPC) que l'instance de base de données Neptune.

Avant de commencer, vous devez exécuter les actions suivantes :
+ Vérifiez que la version 8.11 ou ultérieure de Node.js est installée. Dans le cas contraire, téléchargez et installez Node.js à partir du [site web Nodejs.org](https://nodejs.org).

**Pour se connecter à Neptune à l'aide de Node.js**

1. Entrez ce qui suit pour installer le package `gremlin-javascript` :

   ```
   npm install gremlin
   ```

1. Créez un fichier nommé `gremlinexample.js` et ouvrez-le dans un éditeur de texte.

1. Copiez ce qui suit dans le fichier `gremlinexample.js`. Remplacez *your-neptune-endpoint* par l'adresse de votre instance de base de données Neptune.

   Consultez la section [Connexion aux points de terminaison Amazon Neptune](feature-overview-endpoints.md) pour découvrir comment trouver l'adresse de votre instance de base de données Neptune.

   ```
   const gremlin = require('gremlin');
   const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;
   const Graph = gremlin.structure.Graph;
   
   dc = new DriverRemoteConnection('wss://your-neptune-endpoint:8182/gremlin',{});
   
   const graph = new Graph();
   const g = graph.traversal().withRemote(dc);
   
   g.V().limit(1).count().next().
       then(data => {
           console.log(data);
           dc.close();
       }).catch(error => {
           console.log('ERROR', error);
           dc.close();
       });
   ```

1. Pour exécuter l'exemple, entrez la commande suivante :

   ```
   node gremlinexample.js
   ```

L'exemple précédent renvoie le nombre d'un seul sommet dans le graphique en utilisant la traversée `g.V().limit(1).count().next()`. Pour interroger quelque chose d'autre, remplacez la traversée par une autre traversée Gremlin avec l'une des méthodes de fin appropriées.

**Note**  
La partie finale de la requête Gremlin, `next()`, est obligatoire pour soumettre la traversée au serveur à des fins d'évaluation. Si vous n'incluez pas cette méthode ou une autre méthode équivalente, la requête ne sera pas soumise à l'instance de base de données Neptune.

Les méthodes suivantes soumettent la requête à l'instance de base de données Neptune :
+ `toList()`
+ `toSet()`
+ `next()`
+ `nextTraverser()`
+ `iterate()`

Utilisez `next()` si vous avez besoin que les résultats de la requête soient sérialisés et renvoyés, ou `iterate()` dans le cas contraire.

**Important**  
Il s'agit d'un exemple Node.js autonome. Si vous envisagez d'exécuter un code de ce type dans une AWS Lambda fonction, consultez [Exemples de fonctions Lambda](lambda-functions-examples.md) pour plus de détails sur l'utilisation JavaScript efficace dans une fonction Neptune Lambda.

## Authentification IAM
<a name="access-graph-gremlin-nodejs-iam"></a>

Neptune prend en charge l'[authentification IAM](iam-auth-enable.md) pour contrôler l'accès à votre cluster de base de données. Si l'authentification IAM est activée, vous devez utiliser la signature Signature version 4 pour authentifier vos demandes. Pour obtenir des instructions détaillées et des exemples de code pour la connexion à partir d'un JavaScript client, consultez[Connexion aux bases de données Amazon Neptune à l'aide de l'authentification IAM avec G705 JavaScript](gremlin-javascript-iam-auth.md).

# Utilisation de Go pour se connecter à une instance de base de données Neptune
<a name="access-graph-gremlin-go"></a>

**Important**  
Le choix de la bonne version du pilote TinkerPop Apache G705 est essentiel pour garantir la compatibilité avec la version de votre moteur Neptune. L'utilisation d'une version incompatible peut entraîner des échecs de connexion ou un comportement inattendu. Pour obtenir des informations détaillées sur la compatibilité des versions, consultez[Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md).

**Note**  
Les versions 3.5.x de gremlingo sont rétrocompatibles avec les versions 3.4.x tant que vous n'utilisez que les fonctionnalités TinkerPop 3.4.x dans les requêtes Gkremlin que vous écrivez.

La section suivante vous accompagne dans l'exécution d'un exemple Go qui se connecte à une instance de base de données Amazon Neptune et effectue une traversée Gremlin.

Vous devez suivre ces instructions à partir d'une instance Amazon EC2 dans le même cloud privé virtuel (VPC) (VPC) que l'instance de base de données Neptune.

Avant de commencer, vous devez exécuter les actions suivantes :
+ Téléchargez et installez Go 1.17 ou version ultérieure depuis le site web [go.dev](https://go.dev/dl/).

**Pour se connecter à Neptune à l'aide de Go**

1. À partir d'un répertoire vide, initialisez un nouveau module Go :

   ```
   go mod init example.com/gremlinExample
   ```

1. Ajoutez gremlin-go comme dépendance du nouveau module :

   ```
   go get github.com/apache/tinkerpop/gremlin-go/v3/driver
   ```

1. Créez un fichier nommé `gremlinExample.go` et ouvrez-le dans un éditeur de texte.

1. Copiez ce qui suit dans le fichier `gremlinExample.go`, en remplaçant *`(your neptune endpoint)`* par l'adresse de l'instance de base de données Neptune :

   ```
   package main
   
   import (
     "fmt"
     gremlingo "github.com/apache/tinkerpop/gremlin-go/v3/driver"
   )
   
   func main() {
     // Creating the connection to the server.
     driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection("wss://(your neptune endpoint):8182/gremlin",
       func(settings *gremlingo.DriverRemoteConnectionSettings) {
         settings.TraversalSource = "g"
       })
     if err != nil {
       fmt.Println(err)
       return
     }
     // Cleanup
     defer driverRemoteConnection.Close()
   
     // Creating graph traversal
     g := gremlingo.Traversal_().WithRemote(driverRemoteConnection)
   
     // Perform traversal
     results, err := g.V().Limit(2).ToList()
     if err != nil {
       fmt.Println(err)
       return
     }
     // Print results
     for _, r := range results {
       fmt.Println(r.GetString())
     }
   }
   ```
**Note**  
Le format du certificat Neptune TLS n'est actuellement pas pris en charge sur Go 1.18 ou version supérieure avec macOS et peut générer une erreur 509 lorsque vous essayez d'établir une connexion. Pour les tests locaux, cela peut être ignoré en ajoutant « crypto/tls » aux importations et en modifiant les paramètres `DriverRemoteConnection` comme suit :  

   ```
   // Creating the connection to the server.
   driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection("wss://your-neptune-endpoint:8182/gremlin",
     func(settings *gremlingo.DriverRemoteConnectionSettings) {
         settings.TraversalSource = "g"
         settings.TlsConfig = &tls.Config{InsecureSkipVerify: true}
     })
   ```

1. Pour exécuter l'exemple, entrez la commande suivante :

   ```
   go run gremlinExample.go
   ```

La requête Gremlin à la fin de cet exemple renvoie les sommets (`(g.V().Limit(2))`) dans une liste. Cette tranche est ensuite itérée et imprimée avec la fonction `fmt.Println` standard.

**Note**  
La partie finale de la requête Gremlin, `ToList()`, est obligatoire pour soumettre la traversée au serveur à des fins d'évaluation. Si vous n'incluez pas cette méthode ou une autre méthode équivalente, la requête ne sera pas soumise à l'instance de base de données Neptune.

Les méthodes suivantes soumettent la requête à l'instance de base de données Neptune :
+ `ToList()`
+ `ToSet()`
+ `Next()`
+ `GetResultSet()`
+ `Iterate()`

L'exemple précédent renvoie les deux premier vertex du graphe en utilisant la traversée `g.V().Limit(2).ToList()`. Pour interroger quelque chose d'autre, remplacez la traversée par une autre traversée Gremlin avec l'une des méthodes de fin appropriées.

## Authentification IAM
<a name="access-graph-gremlin-go-iam"></a>

Neptune prend en charge l'[authentification IAM](iam-auth-enable.md) pour contrôler l'accès à votre cluster de base de données. Si l'authentification IAM est activée, vous devez utiliser la signature Signature version 4 pour authentifier vos demandes. Pour obtenir des instructions détaillées et des exemples de code pour la connexion à partir d'un client Go, consultez[Connexion aux bases de données Amazon Neptune à l'aide de l'authentification IAM avec Gremlin Go](gremlin-go-iam-auth.md).

# Utiliser le AWS SDK pour exécuter des requêtes Gremlin
<a name="access-graph-gremlin-sdk"></a>

Avec le AWS SDK, vous pouvez exécuter des requêtes G705 sur votre graphe Neptune à l'aide du langage de programmation de votre choix. Le SDK de l'API de données Neptune (nom du service`neptunedata`) fournit l'[ExecuteGremlinQuery](https://docs.aws.amazon.com/neptune/latest/data-api/API_ExecuteGremlinQuery.html)action permettant de soumettre des requêtes Gremlin.

Vous devez exécuter ces exemples depuis une instance Amazon EC2 dans le même cloud privé virtuel (VPC) que votre cluster de base de données Neptune, ou depuis un emplacement disposant d'une connectivité réseau avec le point de terminaison de votre cluster.

Vous trouverez ci-dessous des liens directs vers la documentation de référence `neptunedata` de l'API pour le service dans chaque langue du SDK :


| Langage de programmation | Référence de l'API neptunedata | 
| --- | --- | 
| C\$1\$1 | [https://sdk.amazonaws.com/cpp/api/LATEST/aws-cpp-sdk-neptunedata/html/annotated.html](https://sdk.amazonaws.com/cpp/api/LATEST/aws-cpp-sdk-neptunedata/html/annotated.html) | 
| Go | [https://docs.aws.amazon.com/sdk-for-go/api/service/neptunedata/](https://docs.aws.amazon.com/sdk-for-go/api/service/neptunedata/) | 
| Java | [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/neptunedata/package-summary.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/neptunedata/package-summary.html) | 
| JavaScript | [https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-neptunedata/](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-neptunedata/) | 
| Kotlin | [https://sdk.amazonaws.com/kotlin/api/latest/neptunedata/index.html](https://sdk.amazonaws.com/kotlin/api/latest/neptunedata/index.html) | 
| .NET | [https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Neptunedata/NNeptunedata.html](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Neptunedata/NNeptunedata.html) | 
| PHP | [https://docs.aws.amazon.com/aws-sdk-php/v3/api/namespace-Aws.Neptunedata.html](https://docs.aws.amazon.com/aws-sdk-php/v3/api/namespace-Aws.Neptunedata.html) | 
| Python | [https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/neptunedata.html](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/neptunedata.html) | 
| Ruby | [https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Neptunedata.html](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Neptunedata.html) | 
| Rust | [https://crates.io/crates/aws-sdk-neptunedata](https://crates.io/crates/aws-sdk-neptunedata) | 
| INTERFACE DE LIGNE DE COMMANDE (CLI) | [https://docs.aws.amazon.com/cli/latest/reference/neptunedata/](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/) | 

## Exemples du AWS SDK Gremlin
<a name="access-graph-gremlin-sdk-examples"></a>

Les exemples suivants montrent comment configurer un `neptunedata` client, exécuter une requête Gremlin et imprimer les résultats. Remplacez *YOUR\$1NEPTUNE\$1HOST* et *YOUR\$1NEPTUNE\$1PORT* par le point de terminaison et le port de votre cluster de base de données Neptune.

**Configuration du délai d'expiration et des nouvelles tentatives côté client**  
Le délai d'attente du client SDK contrôle le temps d'attente d'une réponse par le *client*. Il ne contrôle pas la durée d'exécution de la requête sur le serveur. Si le client expire avant la fin du serveur, la requête peut continuer à s'exécuter sur Neptune alors que le client n'a aucun moyen de récupérer les résultats.  
[Nous vous recommandons de définir le délai de lecture côté client sur `0` (aucun délai d'attente) ou sur une valeur supérieure d'au moins quelques secondes au paramètre neptune\$1query\$1timeout côté serveur sur votre cluster de base de données Neptune.](parameters.md#parameters-db-cluster-parameters-neptune_query_timeout) Cela permet à Neptune de contrôler l'expiration du délai d'expiration des requêtes.  
Nous recommandons également de fixer le nombre maximum de tentatives à `1` (aucune tentative). Si le SDK réessaie une requête toujours en cours d'exécution sur le serveur, cela peut entraîner des opérations dupliquées. Cela est particulièrement important pour les requêtes de mutation, où une nouvelle tentative peut entraîner des écritures dupliquées involontaires.

------
#### [ Python ]

1. Suivez les [instructions d'installation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) pour installer Boto3.

1. Créez un fichier nommé `gremlinExample.py` et collez le code suivant :

   ```
   import boto3
   import json
   from botocore.config import Config
   
   # Disable the client-side read timeout and retries so that
   # Neptune's server-side neptune_query_timeout controls query duration.
   client = boto3.client(
       'neptunedata',
       endpoint_url=f'https://YOUR_NEPTUNE_HOST:YOUR_NEPTUNE_PORT',
       config=Config(read_timeout=None, retries={'total_max_attempts': 1})
   )
   
   # Use the untyped GraphSON v3 serializer for a cleaner JSON response.
   response = client.execute_gremlin_query(
       gremlinQuery='g.V().limit(1)',
       serializer='application/vnd.gremlin-v3.0+json;types=false'
   )
   
   print(json.dumps(response['result'], indent=2))
   ```

1. Exécutez l'exemple : `python gremlinExample.py`

------
#### [ Java ]

1. Suivez les [instructions d'installation](https://docs.aws.amazon.com//sdk-for-java/latest/developer-guide/setup.html) pour configurer le AWS SDK for Java.

1. Utilisez le code suivant pour configurer une`NeptunedataClient`, exécuter une requête Gremlin et imprimer le résultat :

   ```
   import java.net.URI;
   import java.time.Duration;
   import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
   import software.amazon.awssdk.core.retry.RetryPolicy;
   import software.amazon.awssdk.services.neptunedata.NeptunedataClient;
   import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinQueryRequest;
   import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinQueryResponse;
   
   // Disable the client-side timeout and retries so that
   // Neptune's server-side neptune_query_timeout controls query duration.
   NeptunedataClient client = NeptunedataClient.builder()
       .endpointOverride(URI.create("https://YOUR_NEPTUNE_HOST:YOUR_NEPTUNE_PORT"))
       .overrideConfiguration(ClientOverrideConfiguration.builder()
           .apiCallTimeout(Duration.ZERO)
           .retryPolicy(RetryPolicy.none())
           .build())
       .build();
   
   // Use the untyped GraphSON v3 serializer for a cleaner JSON response.
   ExecuteGremlinQueryRequest request = ExecuteGremlinQueryRequest.builder()
       .gremlinQuery("g.V().limit(1)")
       .serializer("application/vnd.gremlin-v3.0+json;types=false")
       .build();
   
   ExecuteGremlinQueryResponse response = client.executeGremlinQuery(request);
   
   System.out.println(response.result().toString());
   ```

------
#### [ JavaScript ]

1. Suivez les [instructions d'installation](https://docs.aws.amazon.com//sdk-for-javascript/v3/developer-guide/getting-started-nodejs.html) pour configurer le AWS SDK pour JavaScript. Installez le package client neptunedata :. `npm install @aws-sdk/client-neptunedata`

1. Créez un fichier nommé `gremlinExample.js` et collez le code suivant :

   ```
   import { NeptunedataClient, ExecuteGremlinQueryCommand } from "@aws-sdk/client-neptunedata";
   import { NodeHttpHandler } from "@smithy/node-http-handler";
   
   const config = {
       endpoint: "https://YOUR_NEPTUNE_HOST:YOUR_NEPTUNE_PORT",
       // Disable the client-side request timeout so that
       // Neptune's server-side neptune_query_timeout controls query duration.
       requestHandler: new NodeHttpHandler({
           requestTimeout: 0
       }),
       maxAttempts: 1
   };
   
   const client = new NeptunedataClient(config);
   
   // Use the untyped GraphSON v3 serializer for a cleaner JSON response.
   const input = {
       gremlinQuery: "g.V().limit(1)",
       serializer: "application/vnd.gremlin-v3.0+json;types=false"
   };
   
   const command = new ExecuteGremlinQueryCommand(input);
   const response = await client.send(command);
   
   console.log(JSON.stringify(response, null, 2));
   ```

1. Exécutez l'exemple : `node gremlinExample.js`

------

# Indicateurs de requête Gremlin
<a name="gremlin-query-hints"></a>

Vous pouvez utiliser des indicateurs de requête afin de spécifier des stratégies d'optimisation et d'évaluation pour une requête Gremlin particulière dans Amazon Neptune. 

Les indicateurs de requête sont spécifiés en ajoutant une étape `withSideEffect` à la requête avec la syntaxe suivante.

```
g.withSideEffect(hint, value)
```
+ *hint* : identifie le type d'indicateur à appliquer.
+ *value* : détermine le comportement de l'aspect du système pris en compte.

Par exemple, le code suivant montre comment inclure un indicateur `repeatMode` dans une traversée Gremlin.

**Note**  
Tous les effets secondaires d'indicateurs de requête Gremlin sont préfixés avec `Neptune#`.

```
g.withSideEffect('Neptune#repeatMode', 'DFS').V("3").repeat(out()).times(10).limit(1).path()
```

La requête précédente demande au moteur Neptune de parcourir le graphe *en profondeur en premier* (`DFS`) au lieu du mode par défaut, *dans la largeur en premier* (`BFS`).

Les sections suivantes fournissent de plus amples informations sur les indicateurs de requête disponibles et leur utilisation.

**Topics**
+ [Indicateur de requête Gremlin repeatMode](gremlin-query-hints-repeatMode.md)
+ [Indicateur de requête Gremlin noReordering](gremlin-query-hints-noReordering.md)
+ [Indicateur de requête Gremlin typePromotion](gremlin-query-hints-typePromotion.md)
+ [Indicateur de requête Gremlin useDFE](gremlin-query-hints-useDFE.md)
+ [Indicateurs de requête Gremlin pour l'utilisation du cache de résultats](gremlin-query-hints-results-cache.md)

# Indicateur de requête Gremlin repeatMode
<a name="gremlin-query-hints-repeatMode"></a>

L’indicateur de requête Neptune `repeatMode` indique la façon dont le moteur Neptune évalue l’étape `repeat()` dans une traversée Gremlin : largeur en premier, profondeur en premier ou profondeur en premier par blocs.

Le mode d'évaluation de l'étape `repeat()` est important lorsqu'il est utilisé pour rechercher ou suivre un chemin, au lieu de simplement répéter une étape un nombre limité de fois.

## Syntaxe
<a name="gremlin-query-hints-repeatMode-syntax"></a>

L'indicateur de requête `repeatMode` est spécifié en ajoutant une étape `withSideEffect` à la requête.

```
g.withSideEffect('Neptune#repeatMode', 'mode').gremlin-traversal
```

**Note**  
Tous les effets secondaires d'indicateurs de requête Gremlin sont préfixés avec `Neptune#`.

**Modes disponibles**
+ `BFS`

  (Breadth-First Search) Recherche dans la largeur en premier

  Mode d'exécution par défaut pour l'étape `repeat()`. Ce mode permet d'obtenir tous les nœuds de même niveau avant d'aller plus en profondeur dans le chemin.

  Cette version est gourmande en mémoire et les frontières peuvent être très étendues. Le risque que la requête manque de mémoire et soit annulée par le moteur Neptune est plus élevé. Ce mode correspond au plus près aux autres implémentations Gremlin.
+ `DFS`

  (Depth-First Search) Recherche en profondeur en premier

  Suit chaque chemin jusqu'à la profondeur maximale avant de passer à la solution suivante.

  Ce mode utilise moins de mémoire. Il peut offrir de meilleures performances dans des situations comme la recherche d'un chemin unique à partir d'un point de départ vers plusieurs tronçons.
+ `CHUNKED_DFS`

  (Chunked Depth-First Search) Recherche en profondeur en premier par blocs

  Approche hybride qui explore le graphe en profondeur en premier par blocs de 1 000 nœuds, plutôt que 1 nœud (`DFS`) ou tous les nœuds (`BFS)`.

  Le moteur Neptune extrait jusqu'à 1 000 nœuds à chaque niveau avant de suivre le chemin plus en profondeur.

  Cela constitue un bon compromis entre la vitesse et l'utilisation de la mémoire. 

  Cette approche s'avère également utile si vous souhaitez utiliser la mode `BFS`, mais la que requête utilise trop de mémoire.



## Exemple
<a name="gremlin-query-hints-repeatMode-example"></a>

La section suivante décrit l'effet du mode de répétition sur un parcours Gremlin.

Dans Neptune, le mode par défaut pour l'étape `repeat()` consiste à effectuer une stratégie d'exécution dans la largeur en premier (`BFS`) pour toutes les traversées. 

Dans la plupart des cas, l' TinkerGraph implémentation utilise la même stratégie d'exécution, mais dans certains cas, elle modifie l'exécution d'une traversée. 

Par exemple, l' TinkerGraph implémentation modifie la requête suivante.

```
g.V("3").repeat(out()).times(10).limit(1).path()
```

L'étape `repeat()` de ce parcours est « déroulée » dans le parcours suivant, ce qui se traduit par une stratégie en profondeur en premier (`DFS`).

```
g.V(<id>).out().out().out().out().out().out().out().out().out().out().limit(1).path()
```

**Important**  
Le moteur de requête Neptune ne procède pas ainsi automatiquement.

Breadth-first (`BFS`) est la stratégie d'exécution par défaut et est similaire TinkerGraph dans la plupart des cas. Cependant, il y a certains cas où les stratégies en profondeur en premier (`DFS`) sont préférables.

 

**BFS (valeur par défaut)**  
BFS (dans la largeur en premier) est la stratégie d'exécution par défaut pour l'opérateur `repeat()`.

```
g.V("3").repeat(out()).times(10).limit(1).path()
```

Le moteur Neptune explore entièrement les premières frontières à neuf tronçons avant de rechercher une solution à partir du dixième tronçon. Cette approche est efficace dans de nombreux cas, notamment dans celui d'une requête au chemin le plus court.

Cependant, dans l'exemple précédent, le parcours serait beaucoup plus rapide à l'aide du mode profondeur en premier (`DFS`) pour l'opérateur `repeat()`.

**DFS**  
La requête suivante utilise le mode `DFS` (profondeur en premier) pour l'opérateur `repeat()`.

```
g.withSideEffect("Neptune#repeatMode", "DFS").V("3").repeat(out()).times(10).limit(1)
```

Ce mode suit chaque solution jusqu'à la profondeur maximale avant d'explorer la solution suivante. 

# Indicateur de requête Gremlin noReordering
<a name="gremlin-query-hints-noReordering"></a>

Lorsque vous soumettez une traversée Gremlin, le moteur de requête Neptune étudie sa structure et réorganise les parties de la requête, en tentant de réduire la quantité de travail nécessaire pour l'évaluation et les temps de réponse de la requête. Par exemple, un parcours avec plusieurs contraintes, telles que plusieurs étapes `has()`, n'est généralement pas évalué dans l’ordre donné. Au lieu de cela, il est réorganisé une fois que la requête a été vérifiée avec une analyse statique.

Le moteur de requête Neptune essaie d'identifier la contrainte la plus sélective et exécute celle-ci en premier. Cela se traduit souvent par de meilleures performances, mais l'ordre dans lequel Neptune choisit d'évaluer la requête peut ne pas toujours être optimal.

Si vous connaissez les caractéristiques exactes des données et que vous souhaitez imposer manuellement l'ordre d'exécution de la requête, vous pouvez utiliser l'indicateur de requête Neptune `noReordering` pour demander que la requête soit évaluée dans l'ordre donné.

## Syntaxe
<a name="gremlin-query-hints-noReordering-syntax"></a>

L'indicateur de requête `noReordering` est spécifié en ajoutant une étape `withSideEffect` à la requête.

```
g.withSideEffect('Neptune#noReordering', true or false).gremlin-traversal
```

**Note**  
Tous les effets secondaires d'indicateurs de requête Gremlin sont préfixés avec `Neptune#`.

**Valeurs disponibles**
+ `true`
+ `false`

# Indicateur de requête Gremlin typePromotion
<a name="gremlin-query-hints-typePromotion"></a>

Lorsque vous soumettez une traversée Gremlin qui filtre une valeur ou une plage numérique, le moteur de requête Neptune doit normalement utiliser la promotion de type lorsqu'il exécute la requête. Autrement dit, il doit examiner les valeurs de tous les types susceptibles de contenir la valeur sur laquelle porte le filtre.

Par exemple, si vous filtrez les valeurs égales à 55, le moteur doit rechercher les entiers égaux à 55, les entiers longs égaux à 55L, les nombres flottants égaux à 55,0, etc. Chaque promotion de type implique une recherche supplémentaire au niveau du stockage, ce qui peut entraîner un délai étonnamment long pour terminer une requête apparemment simple.

Supposons que vous recherchiez tous les sommets dont la propriété correspondant à l'âge du client est supérieure à 5 :

```
g.V().has('customerAge', gt(5))
```

Pour exécuter cette traversée de manière approfondie, Neptune doit développer la requête afin d'examiner tous les types numériques vers lesquels la valeur que vous recherchez pourrait être promue. Dans ce cas, le filtre `gt` doit être appliqué pour tout entier supérieur à 5, tout long supérieur à 5L, tout flottant supérieur à 5,0 et tout double supérieur à 5,0. Étant donné que chacune de ces promotions nécessite une recherche supplémentaire sur le stockage, vous verrez plusieurs filtres par filtre numérique lorsque vous exécuterez l'[API Gremlin `profile`](gremlin-profile-api.md) pour cette requête, et son exécution prendra beaucoup plus de temps que prévu.

Souvent, la promotion de type n'est pas nécessaire, car vous savez déjà que vous n'avez besoin de trouver que les valeurs d'un type spécifique. Dans ce cas, vous pouvez accélérer considérablement les requêtes en utilisant l'indicateur de requête `typePromotion` afin de désactiver la promotion de type.

## Syntaxe
<a name="gremlin-query-hints-typePromotion-syntax"></a>

L'indicateur de requête `typePromotion` est spécifié en ajoutant une étape `withSideEffect` à la requête.

```
g.withSideEffect('Neptune#typePromotion', true or false).gremlin-traversal
```

**Note**  
Tous les effets secondaires d'indicateurs de requête Gremlin sont préfixés avec `Neptune#`.

**Valeurs disponibles**
+ `true`
+ `false`

Pour désactiver la promotion de type pour la requête ci-dessus, vous devez utiliser :

```
g.withSideEffect('Neptune#typePromotion', false).V().has('customerAge', gt(5))
```

# Indicateur de requête Gremlin useDFE
<a name="gremlin-query-hints-useDFE"></a>

Utilisez cet indicateur de requête afin d'activer l'utilisation du DFE pour exécuter la requête. Par défaut, Neptune n'utilise pas le DFE sans que cet indicateur de requête ne soit défini sur `true`, car le paramètre d'instance [neptune\$1dfe\$1query\$1engine](parameters.md#parameters-instance-parameters-neptune_dfe_query_engine) est défini par défaut sur `viaQueryHint`. Si vous définissez ce paramètre d'instance sur `enabled`, le moteur DFE est utilisé pour toutes les requêtes, à l'exception de celles dont l'indicateur de requête `useDFE` est défini sur `false`.

Exemple d'activation du DFE pour une requête :

```
g.withSideEffect('Neptune#useDFE', true).V().out()
```

# Indicateurs de requête Gremlin pour l'utilisation du cache de résultats
<a name="gremlin-query-hints-results-cache"></a>

Les indicateurs de requête suivants peuvent être utilisés lorsque le [cache des résultats de requête](gremlin-results-cache.md) est activé.

## Indicateur de requête Gremlin `enableResultCache`
<a name="gremlin-query-hints-results-cache-enableResultCache"></a>

Lorsque l'indicateur de requête `enableResultCache` a une valeur égale à `true`, les résultats de la requête sont renvoyés à partir du cache s'ils ont déjà été mis en cache. Dans le cas contraire, de nouveaux résultats sont renvoyés et mis en cache jusqu'à ce qu'ils soient effacés de celui-ci. Par exemple :

```
g.with('Neptune#enableResultCache', true)
 .V().has('genre','drama').in('likes')
```

Plus tard, vous pourrez accéder aux résultats mis en cache en émettant à nouveau exactement la même requête.

Si la valeur de cet indicateur de requête est `false` ou si elle n'est pas présente, les résultats de la requête ne sont pas mis en cache. Toutefois, l'utilisation du paramètre `false` n'efface pas les résultats mis en cache existants. Pour effacer les résultats mis en cache, utilisez l'indicateur `invalidateResultCache` ou `invalidateResultCachekey`.

## Indicateur de requête Gremlin `enableResultCacheWithTTL`
<a name="gremlin-query-hints-results-cache-enableResultCacheWithTTL"></a>

L'indicateur de requête `enableResultCacheWithTTL` renvoie également les résultats mis en cache s'il y en a, sans affecter la durée de vie (TTL) des résultats déjà présents dans le cache. S'il n'y a actuellement aucun résultat mis en cache, la requête renvoie de nouveaux résultats et les met en cache pendant la durée de vie (TTL) spécifiée par l'indicateur de requête `enableResultCacheWithTTL`. Cette durée de vie est spécifiée en secondes. Par exemple, la requête suivante spécifie une durée de vie de 60 secondes :

```
g.with('Neptune#enableResultCacheWithTTL', 60)
 .V().has('genre','drama').in('likes')
```

Avant la fin des 60 secondes time-to-live, vous pouvez utiliser la même requête (ici`g.V().has('genre','drama').in('likes')`) avec l'indice `enableResultCache` ou l'indice de `enableResultCacheWithTTL` requête pour accéder aux résultats mis en cache.

**Note**  
La durée de vie spécifiée avec `enableResultCacheWithTTL` n'affecte pas les résultats déjà mis en cache.  
Si les résultats ont déjà été mis en cache avec `enableResultCache`, le cache doit d'abord être explicitement vidé avant qu'`enableResultCacheWithTTL` génère de nouveaux résultats et les mette en cache pour le TTL qu'il spécifie.
Si les résultats ont déjà été mis en cache à l'aide de l'indicateur `enableResultCachewithTTL`, cette durée de vie précédente, ou TTL, doit d'abord expirer avant qu'`enableResultCacheWithTTL` génère de nouveaux résultats et les mette en cache pour la durée de vie qu'il spécifie.

Une fois la durée de vie écoulée, les résultats mis en cache pour la requête sont effacés, et toute instance ultérieure de la même requête renverra de nouveaux résultats. Si `enableResultCacheWithTTL` est attaché à cette requête ultérieure, les nouveaux résultats sont mis en cache avec le TTL spécifié.

## Indicateur de requête Gremlin `invalidateResultCacheKey`
<a name="gremlin-query-hints-results-cache-invalidateResultCacheKey"></a>

L'indicateur de requête `invalidateResultCacheKey` peut avoir la valeur `false` ou `true`. Une valeur `true` entraîne l'effacement des résultats mis en cache pour la requête à laquelle `invalidateResultCacheKey` est attaché. Par exemple, dans l'exemple suivant, les résultats mis en cache pour la clé de requête `g.V().has('genre','drama').in('likes')` sont effacés :

```
g.with('Neptune#invalidateResultCacheKey', true)
 .V().has('genre','drama').in('likes')
```

L'exemple de requête ci-dessus n'entraîne pas la mise en cache de ses nouveaux résultats. Vous pouvez inclure `enableResultCache` (ou `enableResultCacheWithTTL`) dans la même requête si vous souhaitez mettre en cache les nouveaux résultats après avoir effacé les résultats existants dans le cache :

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#invalidateResultCacheKey', true)
 .V().has('genre','drama').in('likes')
```

## Indicateur de requête Gremlin `invalidateResultCache`
<a name="gremlin-query-hints-results-cache-invalidateResultCache"></a>

L'indicateur de requête `invalidateResultCache` peut avoir la valeur `false` ou `true`. Une valeur `true` entraîne l'effacement de tous les résultats du cache de résultats. Par exemple :

```
g.with('Neptune#invalidateResultCache', true)
 .V().has('genre','drama').in('likes')
```

L'exemple de requête ci-dessus n'entraîne pas la mise en cache de ses résultats. Vous pouvez inclure `enableResultCache` (ou `enableResultCacheWithTTL`) dans la même requête si vous souhaitez mettre en cache les nouveaux résultats après avoir entièrement vidé le cache existant :

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#invalidateResultCache', true)
 .V().has('genre','drama').in('likes')
```

## Indicateur de requête Gremlin `numResultsCached`
<a name="gremlin-query-hints-results-cache-numResultsCached"></a>

L'indicateur de requête `numResultsCached` ne peut être utilisé qu'avec les requêtes contenant `iterate()`. Il indique le nombre maximal de résultats à mettre en cache pour la requête à laquelle il est attaché. Notez que les résultats mis en cache lorsque `numResultsCached` est présent ne sont pas renvoyés, mais uniquement mis en cache.

Par exemple, la requête suivante spécifie que jusqu'à 100 de ses résultats doivent être mis en cache, mais aucun de ces résultats mis en cache n'est renvoyé :

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#numResultsCached', 100)
 .V().has('genre','drama').in('likes').iterate()
```

Vous pouvez ensuite utiliser une requête comme celle-ci pour récupérer une série de résultats mis en cache (ici, les dix premiers) :

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#numResultsCached', 100)
 .V().has('genre','drama').in('likes').range(0, 10)
```

## Indicateur de requête Gremlin `noCacheExceptions`
<a name="gremlin-query-hints-results-cache-noCacheExceptions"></a>

L'indicateur de requête `noCacheExceptions` peut avoir la valeur `false` ou `true`. Une valeur `true` entraîne la suppression de toutes les exceptions liées au cache de résultats. Par exemple :

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#noCacheExceptions', true)
 .V().has('genre','drama').in('likes')
```

Elle supprime notamment l'exception `QueryLimitExceededException`, qui est déclenchée si les résultats d'une requête sont trop volumineux pour tenir dans le cache de résultats.

# API de statut des requêtes Gremlin
<a name="gremlin-api-status"></a>

Pour obtenir le statut des requêtes Gremlin, utilisez HTTP `GET` ou `POST` pour effectuer une requête au point de terminaison `https://your-neptune-endpoint:port/gremlin/status`. 

## Paramètres des demandes de statut des requêtes Gremlin
<a name="gremlin-api-status-get-request"></a>
+ **queryID** (*facultatif*) : ID d'une requête Gremlin en cours d'exécution. Affiche uniquement le statut de la requête indiquée.
+ **includeWaiting** (*facultatif*) : renvoie le statut de toutes les requêtes en attente.

  Normalement, seules les requêtes en cours sont incluses dans la réponse, mais lorsque le paramètre `includeWaiting` est spécifié, le statut de toutes les requêtes en attente est également renvoyé.

## Syntaxe des réponses de statut des requêtes Gremlin
<a name="gremlin-api-status-get-response-syntax"></a>

```
{
  "acceptedQueryCount": integer,
  "runningQueryCount": integer,
  "queries": [
    {
      "queryId":"guid",
      "queryEvalStats":
        {
          "waited": integer,
          "elapsed": integer,
          "cancelled": boolean
        },
      "queryString": "string"
    }
  ]
}
```

## Valeurs des réponses de statut des requêtes Gremlin
<a name="gremlin-api-status-get-response-values"></a>
+ **acceptedQueryCount**— Le nombre de requêtes acceptées mais non encore terminées, y compris les requêtes dans la file d'attente.
+ **runningQueryCount**— Le nombre de requêtes Gkremlin en cours d'exécution.
+ **queries** : requêtes Gremlin actuelles.
+ **queryID** : identifiant GUID de la requête. Neptune attribue automatiquement cette valeur d'ID à chaque requête, mais vous pouvez également attribuer votre propre ID (voir [Injection d'un ID personnalisé dans une requête Neptune Gremlin ou SPARQL](features-query-id.md)).
+ **queryEvalStats**— Statistiques pour cette requête.
+ **subqueries** : nombre de sous-requêtes de cette requête.
+ **elapsed** : nombre de microsecondes d'exécution de la requête jusqu'au moment T.
+ **cancelled** : true indique que la requête a été annulée.
+ **queryString** : requête soumise. Celle-ci est tronquée à 1 024 caractères si elle est plus longue que cela.
+ **waited** : indique la durée d'attente de la requête, en millisecondes.

## Exemple de statut de requête Gremlin
<a name="gremlin-api-status-get-example"></a>

Voici un exemple de commande de demande du statut utilisant `curl` et la demande HTTP `GET`.

```
curl https://your-neptune-endpoint:port/gremlin/status
```

Cette sortie affiche une seule requête en cours d'exécution.

```
{
  "acceptedQueryCount":9,
  "runningQueryCount":1,
  "queries": [
    {
      "queryId":"fb34cd3e-f37c-4d12-9cf2-03bb741bf54f",
      "queryEvalStats":
        {
          "waited": 0,
          "elapsed": 23,
          "cancelled": false
        },
      "queryString": "g.V().out().count()"
    }
  ]
}
```

# Annulation de requêtes Gremlin
<a name="gremlin-api-status-cancel"></a>

Pour obtenir le statut des requêtes Gremlin, utilisez HTTP `GET` ou `POST` pour effectuer une requête au point de terminaison `https://your-neptune-endpoint:port/gremlin/status`.

## Paramètres des demandes d'annulation des requêtes Gremlin
<a name="gremlin-api-status-cancel-request"></a>
+ **cancelQuery** : obligatoire pour l'annulation. Ce paramètre n'a aucune valeur correspondante.
+ **queryId** : ID de la requête Gremlin en cours d'exécution à annuler.

## Exemple d'annulation de requêtes Gremlin
<a name="gremlin-api-status-cancel-example"></a>

Voici un exemple de commande `curl` pour annuler une requête.

```
curl https://your-neptune-endpoint:port/gremlin/status \
  --data-urlencode "cancelQuery" \
  --data-urlencode "queryId=fb34cd3e-f37c-4d12-9cf2-03bb741bf54f"
```

L'annulation réussie renvoie le code HTTP `200` OK.

# Prise en charge des sessions basées sur des scripts Gremlin
<a name="access-graph-gremlin-sessions"></a>

Vous pouvez utiliser des sessions Gremlin avec des transactions implicites dans Amazon Neptune. Pour plus d'informations sur les sessions G705, consultez la section [Considering Sessions](http://tinkerpop.apache.org/docs/current/reference/#sessions) dans la TinkerPop documentation Apache. Les sections ci-dessous décrivent comment utiliser les sessions Gremlin avec Java.

**Important**  
Actuellement, Neptune peut conserver une session basée sur des scripts ouverte jusqu'à 10 minutes. Si vous ne fermez pas votre session avant cela, la session expire et tout ce qu'elle contient est annulé.

**Topics**
+ [Sessions Gremlin dans la console Gremlin](#access-graph-gremlin-sessions-console)
+ [Sessions Gremlin dans la variante du langage Gremlin](#access-graph-gremlin-sessions-glv)

## Sessions Gremlin dans la console Gremlin
<a name="access-graph-gremlin-sessions-console"></a>

Si vous créez une connexion à distance sur la console Gremlin sans le paramètre `session`, la connexion à distance est créée en mode *sans session*. Dans ce mode, chaque demande envoyée au serveur est traitée comme une transaction complète en elle-même, et aucun état n'est enregistré entre les demandes. Si une demande échoue, seule cette demande est annulée.

Si vous créez une connexion à distance qui *utilise* le paramètre `session`, vous créez une session basée sur des scripts qui dure jusqu'à ce que vous fermiez la connexion distante. Chaque session est identifiée par un UUID unique que la console génère et renvoie.

Voici un exemple d'appel de console qui crée une session. Une fois les requêtes soumises, un autre appel ferme la session et valide les requêtes.

**Note**  
Le client Gremlin doit toujours être fermé pour libérer des ressources côté serveur.

```
gremlin> :remote connect tinkerpop.server conf/neptune-remote.yaml session
  . . .
  . . .
gremlin> :remote close
```

Pour plus d'informations et des exemples, consultez la section [Sessions](http://tinkerpop.apache.org/docs/current/reference/#console-sessions) de la TinkerPop documentation.

Toutes les requêtes que vous exécutez au cours d'une session forment une seule transaction qui n'est pas validée tant que toutes les requêtes n'ont pas abouti et que vous n'avez pas fermé la connexion à distance. Si une requête échoue, ou si vous n'avez pas fermé la connexion avant la fin de la durée de vie de session prise en charge par Neptune, la transaction de session n’est pas validée, et toutes les requêtes qu’elle contient sont annulées.

## Sessions Gremlin dans la variante du langage Gremlin
<a name="access-graph-gremlin-sessions-glv"></a>

Dans la variante du langage Gremlin (GLV), vous devez créer un objet `SessionedClient` pour émettre plusieurs requêtes en une seule transaction, comme dans l'exemple suivant.

```
try {                              // line 1
  Cluster cluster = Cluster.open();                    // line 2
  Client client = cluster.connect("sessionName");      // line 3
   ...
   ...
} finally {
  // Always close. If there are no errors, the transaction is committed; otherwise, it's rolled back.
  client.close();
}
```

La ligne 3 de l'exemple précédent crée l'objet `SessionedClient` selon les options de configuration définies pour le cluster en question. La *sessionName* chaîne que vous transmettez à la méthode de connexion devient le nom unique de la session. Pour éviter les collisions, utilisez un UUID pour le nom.

Le client démarre une transaction de session lorsqu'il est initialisé. Toutes les requêtes que vous exécutez au cours du formulaire de session ne sont validées que lorsque vous appelez `client.close( )`. Là encore, si une seule requête échoue ou si vous n'avez pas fermé la connexion avant la fin de la durée de vie de session prise en charge par Neptune, la transaction de session échoue, et toutes les requêtes qu’elle contient sont annulées.

**Note**  
Le client Gremlin doit toujours être fermé pour libérer des ressources côté serveur.

```
GraphTraversalSource g = traversal().withRemote(conn);

Transaction tx = g.tx();

// Spawn a GraphTraversalSource from the Transaction.
// Traversals spawned from gtx are executed within a single transaction.
GraphTraversalSource gtx = tx.begin();
try {
  gtx.addV('person').iterate();
  gtx.addV('software').iterate();

  tx.commit();
} finally {
    if (tx.isOpen()) {
        tx.rollback();
    }
}
```

# Transactions Gremlin dans Neptune
<a name="access-graph-gremlin-transactions"></a>

Il existe plusieurs contextes dans lesquels les [transactions](transactions.md) Gremlin sont exécutées. Lorsque vous travaillez avec Gremlin, il est important de comprendre le contexte dans lequel vous évoluez et quelles en sont les implications :
+ **`Script-based`** : les demandes sont effectuées à l'aide de chaînes Gremlin basées sur du texte, comme ceci :
  + Avec le pilote Java et `Client.submit(string)`.
  + Avec la console Gremlin et `:remote connect`.
  + Avec l'API HTTP.
+ **`Bytecode-based`** : les demandes sont effectuées à l'aide du bytecode Gremlin sérialisé typique des [variantes du langage Gremlin](https://tinkerpop.apache.org/docs/current/reference/#gremlin-drivers-variants) (GLV).

  Par exemple, avec le pilote Java, `g = traversal().withRemote(...)`.

Pour l'un ou l'autre des contextes ci-dessus, il existe un contexte supplémentaire dans lequel la demande est envoyée sans session ou liée à une session.

**Note**  
 Les transactions Gremlin doivent toujours être validées ou annulées, afin que les ressources côté serveur puissent être libérées. En cas d'erreur lors de la transaction, il est important de réessayer l'ensemble de la transaction et pas uniquement la demande qui a échoué. 

## Demandes sans session
<a name="access-graph-gremlin-transactions-sessionless"></a>

 En l'absence de session, une demande équivaut à une transaction unique.

Pour les scripts, cela implique qu'une ou plusieurs déclarations Gremlin envoyées dans le cadre d'une seule demande sont validées ou annulées en tant que transaction unique. Par exemple :

```
Cluster cluster = Cluster.open();
Client client = cluster.connect(); // sessionless
// 3 vertex additions in one request/transaction:
client.submit("g.addV();g.addV();g.addV()").all().get();
```

Pour le bytecode, une demande sans session est effectuée pour chaque traversée générée et exécutée à partir de `g` :

```
GraphTraversalSource g = traversal().withRemote(...);

// 3 vertex additions in three individual requests/transactions:
g.addV().iterate();
g.addV().iterate();
g.addV().iterate();

// 3 vertex additions in one single request/transaction:
g.addV().addV().addV().iterate();
```

## Demandes liées à une session
<a name="access-graph-gremlin-transactions-session-bound"></a>

Lorsqu'elles sont liées à une session, plusieurs demandes peuvent être appliquées dans le contexte d'une seule transaction.

Pour les scripts, cela implique qu'il n'est pas nécessaire de concaténer toutes les opérations du graphe en une seule valeur de chaîne intégrée :

```
Cluster cluster = Cluster.open();
Client client = cluster.connect(sessionName); // session
try {
    // 3 vertex additions in one request/transaction:
    client.submit("g.addV();g.addV();g.addV()").all().get();
} finally {
    client.close();
}

try {
    // 3 vertex additions in three requests, but one transaction:
    client.submit("g.addV()").all().get(); // starts a new transaction with the same sessionName
    client.submit("g.addV()").all().get();
    client.submit("g.addV()").all().get();
} finally {
    client.close();
}
```

Pour le bytecode, après TinkerPop `3.5.x`, la transaction peut être contrôlée de manière explicite et la session gérée de manière transparente. Les variantes du langage Gremlin (GLV) prennent en charge la syntaxe `tx()` de Gremlin pour effectuer des opérations de type `commit()` ou `rollback()` d'une transaction, comme suit :

```
GraphTraversalSource g = traversal().withRemote(conn);

Transaction tx = g.tx();

// Spawn a GraphTraversalSource from the Transaction.
// Traversals spawned from gtx are executed within a single transaction.
GraphTraversalSource gtx = tx.begin();
try {
    gtx.addV('person').iterate();
    gtx.addV('software').iterate();

    tx.commit();
} finally {
    if (tx.isOpen()) {
        tx.rollback();
    }
}
```

Bien que l'exemple ci-dessus soit écrit en Java, vous pouvez également utiliser cette syntaxe `tx()` en Python, Javascript et .NET.

**Avertissement**  
Les requêtes en lecture seule sans session sont exécutées sous un isolement [SNAPSHOT](transactions-isolation-levels.md), mais les requêtes en lecture seule exécutées dans le cadre d'une transaction explicite sont exécutées sous un isolement [SERIALIZABLE](transactions-isolation-levels.md). Les requêtes en lecture seule exécutées sous un isolement `SERIALIZABLE` entraînent une surcharge plus importante et peuvent bloquer les écritures simultanées ou être bloquées par ces dernières, contrairement à celles exécutées sous un isolement `SNAPSHOT`.

# Utilisation de l'API Gremlin avec Amazon Neptune
<a name="gremlin-api-reference"></a>

**Note**  
Amazon Neptune ne prend pas en charge la propriété `bindings`.

Les demandes HTTPS Gremlin utilisent un point de terminaison unique : `https://your-neptune-endpoint:port/gremlin`. Toutes les connexions Neptune doivent utiliser HTTPS.

Vous pouvez connecter la console Gkremlin à un graphe Neptune directement via. WebSockets

Pour plus d'informations sur la connexion au point de terminaison Gremlin, consultez [Accès au graphe Neptune avec Gremlin](access-graph-gremlin.md).

L'implémentation Amazon Neptune de Gremlin implique des détails et des différences spécifiques que vous devez prendre en compte. Pour de plus amples informations, veuillez consulter [Conformité d'Amazon Neptune avec les normes Gremlin](access-graph-gremlin-differences.md).

Pour plus d'informations sur le langage Gremlin et les traversales, consultez The [Traversal dans la documentation](https://tinkerpop.apache.org/docs/current/reference/#traversal) d'Apache. TinkerPop 

# Mise en cache des résultats de requête dans Amazon Neptune Gremlin
<a name="gremlin-results-cache"></a>

Amazon Neptune prend en charge un cache de résultats pour les requêtes Gremlin.

Vous pouvez activer ce cache, puis utiliser un indicateur de requête pour mettre en cache les résultats d'une requête Gremlin en lecture seule.

Toute réexécution de la requête permet ensuite de récupérer les résultats mis en cache avec une faible latence et sans I/O frais, tant qu'ils sont toujours dans le cache. Ce comportement s'applique pour les requêtes soumises à la fois sur un point de terminaison HTTP et à l'aide de Websockets, sous forme de bytecode ou de chaîne.

**Note**  
Les requêtes envoyées au point de terminaison de profil ne sont pas mises en cache même lorsque le cache de requêtes est activé.

Vous pouvez contrôler le comportement du cache des résultats de requête Neptune de plusieurs manières. Par exemple :
+ Vous pouvez obtenir les résultats mis en cache paginés, par blocs.
+ Vous pouvez spécifier le time-to-live (TTL) pour les requêtes spécifiées.
+ Vous pouvez vider le cache pour certaines requêtes.
+ Vous pouvez vider tout le cache.
+ Vous pouvez configurer le cache afin d'être averti si les résultats dépassent sa taille.

Le cache est maintenu selon une politique least-recently-used (LRU), ce qui signifie qu'une fois que l'espace alloué au cache est plein, les least-recently-used résultats sont supprimés pour faire de la place lorsque de nouveaux résultats sont mis en cache.

**Important**  
Le cache des résultats de requête n'est pas disponible sur les types d'instance `t3.medium` et `t4.medium`.

## Activation du cache des résultats de requête dans Neptune
<a name="gremlin-results-cache-enabling"></a>

 Le cache des résultats des requêtes peut être activé sur toutes les instances d'un cluster ou par instance. Pour activer le cache des résultats sur toutes les instances d'un cluster, définissez le `neptune_result_cache` paramètre dans le cluster `cluster-parameter-group` sur`1`. Pour l'activer sur une instance spécifique, définissez le `neptune_result_cache` paramètre de l'instance `instance-parameter-group` sur`1`. Le paramètre du groupe de paramètres du cluster remplacera la valeur du groupe de paramètres d'instance. 

 Un redémarrage est nécessaire sur toutes les instances concernées pour que les paramètres du cache de résultats soient appliqués. Bien que vous puissiez activer le cache des résultats sur toutes les instances d'un cluster via le`cluster-parameter-group`, chaque instance conserve son propre cache. La fonctionnalité de cache des résultats de requête n'est pas un cache à l'échelle du cluster. 

Une fois le cache des résultats activé, Neptune réserve une partie de la mémoire actuelle à la mise en cache des résultats de requête. Plus le type d'instance que vous utilisez est grand et plus la quantité de mémoire disponible est importante, plus Neptune réserve de mémoire au cache.

Si la mémoire cache des résultats est pleine, Neptune supprime automatiquement least-recently-used (LRU) les résultats mis en cache pour faire place à de nouveaux.

Vous pouvez vérifier le statut actuel du cache de résultats à l'aide de la commande [Statut d’une instance](access-graph-status.md).

## Utilisation d'indicateurs pour mettre en cache les résultats de requête
<a name="gremlin-results-cache-using"></a>

Une fois le cache des résultats de requête activé, vous pouvez utiliser des indicateurs de requête pour contrôler la mise en cache des requêtes. Tous les exemples ci-dessous s'appliquent à la même traversée de requêtes, à savoir :

```
g.V().has('genre','drama').in('likes')
```

### Utilisation de `enableResultCache`
<a name="using-enableResultCache"></a>

Lorsque le cache des résultats de requête est activé, vous pouvez mettre en cache les résultats d'une requête Gremlin à l'aide de l'indicateur de requête `enableResultCache`, comme suit :

```
g.with('Neptune#enableResultCache', true)
 .V().has('genre','drama').in('likes')
```

Neptune vous renvoie ensuite les résultats de la requête et les met également en cache. Plus tard, vous pourrez accéder aux résultats mis en cache en émettant à nouveau exactement la même requête :

```
g.with('Neptune#enableResultCache', true)
 .V().has('genre','drama').in('likes')
```

La clé de cache qui identifie les résultats mis en cache est la chaîne de requête elle-même, à savoir :

```
g.V().has('genre','drama').in('likes')
```

### Utilisation de `enableResultCacheWithTTL`
<a name="using-enableResultCacheWithTTL"></a>

Vous pouvez spécifier la durée pendant laquelle les résultats de la requête doivent être mis en cache à l'aide de l'indicateur de requête `enableResultCacheWithTTL`. Par exemple, la requête suivante indique que les résultats de la requête doivent expirer au bout de 120 secondes :

```
g.with('Neptune#enableResultCacheWithTTL', 120)
 .V().has('genre','drama').in('likes')
```

Là aussi, la clé de cache qui identifie les résultats mis en cache est la chaîne de requête de base :

```
g.V().has('genre','drama').in('likes')
```

Et là aussi, vous pouvez accéder aux résultats mis en cache à l'aide de cette chaîne de requête avec l'indicateur de requête `enableResultCache` :

```
g.with('Neptune#enableResultCache', true)
 .V().has('genre','drama').in('likes')
```

Si 120 secondes ou plus se sont écoulées depuis la mise en cache des résultats, cette requête renverra de nouveaux résultats, et les mettra en cache, sans aucun time-to-live.

Vous pouvez également accéder aux résultats mis en cache en émettant à nouveau la même requête avec l'indicateur de requête `enableResultCacheWithTTL`. Par exemple :

```
g.with('Neptune#enableResultCacheWithTTL', 140)
 .V().has('genre','drama').in('likes')
```

Tant que 120 secondes ne se sont pas écoulées (ce qui correspond au TTL actuellement en vigueur), cette nouvelle requête avec l'indicateur `enableResultCacheWithTTL` renvoie les résultats mis en cache. Après 120 secondes, il renverrait de nouveaux résultats et les mettrait en cache avec un time-to-live délai de 140 secondes.

**Note**  
Si les résultats d'une clé de requête sont déjà mis en cache, la même clé de requête `enableResultCacheWithTTL` ne génère pas de nouveaux résultats et n'a aucun effet sur les time-to-live résultats actuellement mis en cache.  
Si les résultats ont déjà été mis en cache avec `enableResultCache`, le cache doit d'abord être explicitement vidé avant qu'`enableResultCacheWithTTL` génère de nouveaux résultats et les mette en cache pour le TTL qu'il spécifie.
Si les résultats ont déjà été mis en cache à l'aide de l'indicateur `enableResultCachewithTTL`, cette durée de vie précédente, ou TTL, doit d'abord expirer avant qu'`enableResultCacheWithTTL` génère de nouveaux résultats et les mette en cache pour la durée de vie qu'il spécifie.

### Utilisation de `invalidateResultCacheKey`
<a name="using-invalidateResultCacheKey"></a>

Vous pouvez utiliser l'indicateur de requête `invalidateResultCacheKey` pour effacer les résultats mis en cache pour une requête particulière. Par exemple :

```
g.with('Neptune#invalidateResultCacheKey', true)
 .V().has('genre','drama').in('likes')
```

Cette requête vide la partie du cache correspondant à la clé de requête, `g.V().has('genre','drama').in('likes')`, et renvoie de nouveaux résultats pour cette requête.

Vous pouvez également combiner `invalidateResultCacheKey` avec `enableResultCache` ou `enableResultCacheWithTTL`. Par exemple, la requête suivante efface les résultats actuellement mis en cache, met en cache les nouveaux résultats et les renvoie :

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#invalidateResultCacheKey', true)
 .V().has('genre','drama').in('likes')
```

### Utilisation de `invalidateResultCache`
<a name="using-invalidateResultCache"></a>

Vous pouvez utiliser l'indicateur de requête `invalidateResultCache` pour effacer tous les résultats mis en cache dans le cache des résultats de requête. Par exemple :

```
g.with('Neptune#invalidateResultCache', true)
 .V().has('genre','drama').in('likes')
```

Cette requête vide l'intégralité du cache de résultats et renvoie de nouveaux résultats pour la requête.

Vous pouvez également combiner `invalidateResultCache` avec `enableResultCache` ou `enableResultCacheWithTTL`. Par exemple, la requête suivante vide l'intégralité du cache de résultats, met en cache les nouveaux résultats pour cette requête et les renvoie :

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#invalidateResultCache', true)
 .V().has('genre','drama').in('likes')
```

## Pagination des résultats de requête mis en cache
<a name="gremlin-results-cache-paginating"></a>

Supposons que vous ayez déjà mis en cache un grand nombre de résultats comme suit :

```
g.with('Neptune#enableResultCache', true)
 .V().has('genre','drama').in('likes')
```

Supposons maintenant que vous émettiez la requête de plage suivante :

```
g.with('Neptune#enableResultCache', true)
 .V().has('genre','drama').in('likes').range(0,10)
```

Neptune recherche d'abord la clé de cache complète, à savoir `g.V().has('genre','drama').in('likes').range(0,10)`. Si elle n'existe pas, Neptune vérifie ensuite s'il existe une clé pour cette chaîne de requête sans la plage (à savoir `g.V().has('genre','drama').in('likes')`). Lorsqu'il trouve cette clé, Neptune extrait les dix premiers résultats de son cache, conformément à la plage spécifiée.

**Note**  
Si vous utilisez l'indicateur `invalidateResultCacheKey` avec une requête contenant une plage à la fin, Neptune vide la partie du cache correspondant à une requête sans plage s'il ne trouve pas de correspondance exacte entre cette requête et cette plage.

### Utilisation d’`numResultsCached` avec `.iterate()`
<a name="gremlin-results-cache-paginating-numResultsCached"></a>

À l'aide de l'indicateur de requête `numResultsCached`, vous pouvez remplir le cache de résultats sans avoir à renvoyer tous les résultats mis en cache, ce qui peut être utile lorsque vous préférez paginer un grand nombre de résultats.

L'indicateur de requête `numResultsCached` ne fonctionne qu'avec les requêtes se terminant par `iterate()`.

Par exemple, si vous souhaitez mettre en cache les 50 premiers résultats de cet exemple de requête :

```
g.with("Neptune#enableResultCache", true)
 .with("Neptune#numResultsCached", 50)
 .V().has('genre','drama').in('likes').iterate()
```

Dans ce cas, la clé de requête dans le cache est : `g.with("Neptune#numResultsCached", 50).V().has('genre','drama').in('likes')`. Vous pouvez désormais récupérer les 10 premiers résultats mis en cache avec cette requête :

```
g.with("Neptune#enableResultCache", true)
 .with("Neptune#numResultsCached", 50)
 .V().has('genre','drama').in('likes').range(0, 10)
```

Et vous pouvez récupérer les 10 résultats suivants de la requête comme suit :

```
g.with("Neptune#enableResultCache", true)
 .with("Neptune#numResultsCached", 50)
 .V().has('genre','drama').in('likes').range(10, 20)
```

N'oubliez pas d'inclure l'indicateur `numResultsCached`. Il s'agit d'un élément essentiel de la clé de requête. Il doit donc être présent pour pouvoir accéder aux résultats mis en cache.

**Voici quelques points à garder à l'esprit lorsque vous utilisez `numResultsCached` :**
+ **Le nombre que vous indiquez avec `numResultsCached` est appliqué à la fin de la requête.**   Cela signifie, par exemple, que la requête suivante met réellement en cache les résultats dans la plage `(1000, 1500)` :

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 500)
   .V().range(1000, 2000).iterate()
  ```
+ **Le nombre que vous indiquez avec `numResultsCached` spécifie le nombre maximum de résultats à mettre en cache.**   Cela signifie, par exemple, que la requête suivante met réellement en cache les résultats dans la plage `(1000, 2000)` :

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 100000)
   .V().range(1000, 2000).iterate()
  ```
+ **Les résultats mis en cache par les requêtes se terminant par `.range().iterate()` ont leur propre plage.**   Supposons, par exemple, que vous mettiez en cache les résultats à l'aide d'une requête comme celle-ci :

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 500)
   .V().range(1000, 2000).iterate()
  ```

  Pour récupérer les 100 premiers résultats du cache, vous devriez écrire une requête comme celle-ci :

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 500)
   .V().range(1000, 2000).range(0, 100)
  ```

  Ces cent résultats seraient équivalents aux résultats de la requête de base de la plage `(1000, 1100)`.

## Clés de cache de requête utilisées pour localiser les résultats mis en cache
<a name="gremlin-results-cache-query-keys"></a>

Une fois que les résultats d'une requête ont été mis en cache, les requêtes suivantes avec la même *clé de cache de requête* récupèrent les résultats du cache au lieu d'en générer de nouveaux. La clé de cache d'une requête est évaluée comme suit :

1. Tous les indicateurs de requête liés au cache sont ignorés, à l'exception de `numResultsCached`.

1. Une dernière étape `iterate()` est ignorée.

1. Le reste de la requête est ordonné en fonction de sa représentation en bytecode.

La chaîne générée est comparée à un index des résultats de requête déjà présents dans le cache afin de déterminer la requête a accédé au cache.

Prenons, par exemple, cette requête :

```
g.withSideEffect('Neptune#typePromotion', false).with("Neptune#enableResultCache", true)
 .with("Neptune#numResultsCached", 50)
 .V().has('genre','drama').in('likes').iterate()
```

Elle sera stockée en tant que version bytecode de celle-ci :

```
g.withSideEffect('Neptune#typePromotion', false)
 .with("Neptune#numResultsCached", 50)
 .V().has('genre','drama').in('likes')
```

## Exceptions liées au cache de résultats
<a name="gremlin-results-cache-exceptions"></a>

Si les résultats d'une requête que vous essayez de mettre en cache sont trop importants pour tenir dans la mémoire du cache, même après avoir supprimé tout ce qui était déjà mis en cache, Neptune signale une erreur `QueryLimitExceededException`. Aucun résultat n'est renvoyé, et l'exception génère le message d'erreur suivant :

```
The result size is larger than the allocated cache,
      please refer to results cache best practices for options to rerun the query.
```

Vous pouvez supprimer ce message à l'aide de l'indicateur de requête `noCacheExceptions`, comme suit :

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#noCacheExceptions', true)
 .V().has('genre','drama').in('likes')
```

# Réalisation d'upserts efficaces avec les étapes Gremlin `mergeV()` et `mergeE()`
<a name="gremlin-efficient-upserts"></a>

Une insertion conditionnelle (également appelée « upsert ») réutilise un sommet ou une arête qui existe déjà, ou crée l'objet nécessaire dans le cas contraire. Des upserts efficaces peuvent faire une différence significative dans les performances des requêtes Gremlin.

Les upserts vous permettent d'écrire des opérations d'insertion idempotentes : quel que soit le nombre de fois que vous exécutez cette opération, le résultat global est le même. Cela est utile dans les scénarios d'écriture hautement simultanés où les modifications simultanées apportées à la même partie du graphe peuvent forcer une ou plusieurs transactions à revenir en arrière avec une exception `ConcurrentModificationException`, nécessitant ainsi de nouvelles tentatives.

Par exemple, la requête suivante insère un sommet en utilisant l'élément `Map` fourni pour essayer d'abord de trouver un sommet avec le `T.id` `"v-1"`. Si ce sommet est trouvé, il est renvoyé. Dans le cas contraire, un sommet contenant cet `id` et cette propriété est créé par le biais de la clause `onCreate`.

```
g.mergeV([(id):'v-1']).
  option(onCreate, [(label): 'PERSON', 'email': 'person-1@example.org'])
```

## Exécution d'upserts par lots pour améliorer le débit
<a name="gremlin-upserts-batching"></a>

Pour les scénarios d'écriture à haut débit, vous pouvez enchaîner les étapes `mergeV()` et `mergeE()` pour effectuer l'upsert en bloc des sommets et des arêtes. Le traitement par lots réduit la charge transactionnelle liée à l'insertion par upsert d'un grand nombre de sommets et d'arêtes. Vous pouvez ainsi améliorer davantage le débit en augmentant les demandes d'upserts par lots en parallèle à l'aide de plusieurs clients.

En règle générale, nous recommandons d'insérer par upsert environ 200 enregistrements par demande par lots. Un enregistrement correspond à une étiquette ou propriété individuelle de sommet ou d'arête. Par exemple, un sommet doté d'une seule étiquette et de quatre propriétés génère cinq enregistrements. Une arête dotée d'une étiquette et d'une seule propriété génère deux enregistrements. Si vous souhaitez insérer par upsert des lots de sommets, chacun avec une seule étiquette et quatre propriétés, vous devez commencer par une taille de lot de 40, car `200 / (1 + 4) = 40`.

Vous pouvez tester différentes tailles de lots. 200 enregistrements par lot constituent un bon point de départ, mais la taille de lot idéale peut être supérieure ou inférieure en fonction de votre charge de travail. Notez toutefois que Neptune peut limiter le nombre total d'étapes Gremlin par demande. Cette limite n'est pas documentée, mais par mesure de sécurité, essayez de faire en sorte que les demandes ne contiennent pas plus de 1 500 étapes Gremlin. Neptune peut rejeter des demandes en bloc volumineuses comportant plus de 1 500 étapes.

Pour augmenter le débit, vous pouvez insérer par upsert des lots en parallèle à l'aide de plusieurs clients (voir [Création d'écritures Gremlin multithreads efficaces](best-practices-gremlin-multithreaded-writes.md)). Le nombre de clients doit être identique au nombre de threads de travail sur votre instance Neptune Writer, qui est généralement 2 fois le nombre de v CPUs sur le serveur. Par exemple, une `r5.8xlarge` instance possède 32 V CPUs et 64 threads de travail. Pour les scénarios d'écriture à haut débit utilisant une instance `r5.8xlarge`, vous devez utiliser 64 clients écrivant des upserts par lots sur Neptune en parallèle.

Chaque client doit soumettre une demande par lots et attendre qu'elle soit terminée avant de soumettre une autre demande. Bien que les différents clients fonctionnent en parallèle, chacun d'eux soumet des demandes en série. Cela garantit que le serveur reçoit un flux constant de demandes qui occupent tous les threads de travail sans encombrer la file d'attente des demandes côté serveur (voir [Dimensionnement des instances de base de données dans un cluster de bases de données Neptune](feature-overview-db-clusters.md#feature-overview-sizing-instances)).

## Essayer d'éviter les étapes qui génèrent plusieurs traverseurs
<a name="gremlin-upserts-single-traverser"></a>

Lorsqu'une étape Gremlin s'exécute, elle utilise un traverseur entrant et émet un ou plusieurs traverseurs de sortie. Le nombre de traverseurs émis par une étape détermine le nombre de fois que l'étape suivante sera exécutée.

Généralement, lorsque vous effectuez des opérations par lots, vous souhaitez que chaque opération, telle que l'upsert du sommet A, soit exécutée une seule fois, de sorte que la séquence des opérations ressemble à ceci : upsert du sommet A, puis upsert du sommet B, puis upsert du sommet C, etc. Tant qu'une étape ne crée ou ne modifie qu'un seul élément, elle n'émet qu'un seul traverseur, et les étapes représentant l'opération suivante ne sont exécutées qu'une seule fois. Si, en revanche, une opération crée ou modifie plusieurs éléments, elle émet plusieurs traverseurs, ce qui entraîne l'exécution des étapes suivantes plusieurs fois, une fois par traverseur émis. Cela peut obliger la base de données à effectuer des tâches supplémentaires inutiles et, dans certains cas, à créer des sommets, des arêtes ou des valeurs de propriétés supplémentaires superflus.

La requête `g.V().addV()` est un bon exemple de cas où la situation peut dégénérer. Cette requête simple ajoute un sommet pour chaque sommet du graphe, car `V()` émet un traverseur pour chaque sommet du graphe et chacun de ces traverseurs déclenche un appel à `addV()`.

Consultez [Combinaison d'upserts et d'insertions](#gremlin-upserts-and-inserts) pour découvrir comment gérer les opérations qui peuvent émettre plusieurs traverseurs.

## Insertion de sommets par upsert
<a name="gremlin-upserts-vertices"></a>

L'étape `mergeV()` est spécialement conçue pour l'upsert de sommets. Elle utilise comme argument un objet `Map` qui représente les éléments correspondant aux sommets existants dans le graphe. Si aucun élément n'est trouvé, elle utilise cet objet `Map` pour créer un sommet. Cette étape vous permet également de modifier le comportement en cas de création ou de correspondance. Le modulateur `option()` peut alors être associé à des jetons `Merge.onCreate` et `Merge.onMatch` pour contrôler ces comportements respectifs. Consultez la [documentation de TinkerPop référence](https://tinkerpop.apache.org/docs/current/reference/#mergevertex-step) pour plus d'informations sur l'utilisation de cette étape.

Vous pouvez utiliser un ID de sommet pour déterminer si un sommet spécifique existe. Il s'agit de l'approche préférée, car Neptune optimise les upserts pour les cas d'utilisation très concurrents. IDs Par exemple, la requête suivante crée un sommet avec un ID de sommet donné s'il n'existe pas déjà, ou le réutilise s'il existe déjà :

```
g.mergeV([(T.id): 'v-1']).
    option(onCreate, [(T.label): 'PERSON', email: 'person-1@example.org', age: 21]).
    option(onMatch, [age: 22]).
  id()
```

Notez que cette requête se termine par une étape `id()`. Bien que cela ne soit pas strictement nécessaire pour réaliser l'upsert du sommet, une étape `id()` à la fin d'une requête d'upsert garantit que le serveur ne sérialise pas toutes les propriétés du sommet vers le client, ce qui contribue à réduire le coût de verrouillage de la requête.

Vous pouvez également utiliser une propriété de sommet pour identifier un sommet :

```
g.mergeV([email: 'person-1@example.org']).
    option(onCreate, [(T.label): 'PERSON', age: 21]).
    option(onMatch, [age: 22]).
  id()
```

Si possible, utilisez les sommets fournis par l'utilisateur IDs pour créer des sommets, et utilisez-les IDs pour déterminer si un sommet existe lors d'une opération de remontée. Cela permet à Neptune d'optimiser les upserts. Un upsert basé sur un ID peut être nettement plus efficace qu'un upsert basé sur des propriétés lorsque des modifications simultanées sont courantes.

### Enchaînement d'upserts de sommets
<a name="gremlin-upserts-vertices-chaining"></a>

Vous pouvez enchaîner des upserts de sommets pour les insérer dans un lot :

```
g.V('v-1')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-1')
                         .property('email', 'person-1@example.org'))
 .V('v-2')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-2')
                         .property('email', 'person-2@example.org'))
 .V('v-3')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-3')
                         .property('email', 'person-3@example.org'))
 .id()
```

Vous pouvez également utiliser cette syntaxe `mergeV()` :

```
g.mergeV([(T.id): 'v-1', (T.label): 'PERSON', email: 'person-1@example.org']).
  mergeV([(T.id): 'v-2', (T.label): 'PERSON', email: 'person-2@example.org']).
  mergeV([(T.id): 'v-3', (T.label): 'PERSON', email: 'person-3@example.org'])
```

Cependant, comme cette forme de requête inclut des éléments dans les critères de recherche qui sont superflus par rapport à la recherche de base par `id`, elle n'est pas aussi efficace que la requête précédente.

## Exécution d'upserts d'arêtes
<a name="gremlin-upserts-edges"></a>

L'étape `mergeE()` est spécialement conçue pour l'upsert d'arêtes. Elle utilise comme argument un objet `Map` qui représente les éléments correspondant aux arêtes existantes dans le graphe. Si aucun élément n'est trouvé, elle utilise cet objet `Map` pour créer une arête. Cette étape vous permet également de modifier le comportement en cas de création ou de correspondance. Le modulateur `option()` peut alors être associé à des jetons `Merge.onCreate` et `Merge.onMatch` pour contrôler ces comportements respectifs. Consultez la [documentation de TinkerPop référence](https://tinkerpop.apache.org/docs/current/reference/#mergeedge-step) pour plus d'informations sur l'utilisation de cette étape.

Vous pouvez utiliser une arête IDs pour insérer des arêtes de la même manière que vous insérez des sommets à l'aide d'un sommet personnalisé. IDs Là aussi, il s'agit de l'approche préférée, car elle permet à Neptune d'optimiser la requête. Par exemple, la requête suivante crée une arête en fonction de son ID d'arête si elle n'existe pas déjà, ou la réutilise si elle existe déjà. La requête utilise également IDs les `Direction.to` sommets `Direction.from` et si elle doit créer une nouvelle arête :

```
g.mergeE([(T.id): 'e-1']).
    option(onCreate, [(from): 'v-1', (to): 'v-2', weight: 1.0]).
    option(onMatch, [weight: 0.5]).
  id()
```

Notez que cette requête se termine par une étape `id()`. Bien que cela ne soit pas strictement nécessaire pour réaliser l'upsert de l'arête, une étape `id()` à la fin d'une requête d'upsert garantit que le serveur ne sérialise pas toutes les propriétés de l'arête vers le client, ce qui contribue à réduire le coût de verrouillage de la requête.

De nombreuses applications utilisent un sommet personnalisé IDs, mais laissent à Neptune le soin de générer l'arête. IDs Si vous ne connaissez pas l'ID d'une arête, mais que vous connaissez le `to` sommet `from` et IDs, vous pouvez utiliser ce type de requête pour modifier une arête :

```
g.mergeE([(from): 'v-1', (to): 'v-2', (T.label): 'KNOWS']).
  id()
```

Tous les sommets référencés par `mergeE()` doivent exister pour que l'étape crée l'arête.

### Enchaînement d'upserts d'arêtes
<a name="gremlin-upserts-edges-chaining"></a>

Comme pour les upserts de sommets, il est simple d'enchaîner les étapes `mergeE()` pour les demandes en bloc :

```
g.mergeE([(from): 'v-1', (to): 'v-2', (T.label): 'KNOWS']).
  mergeE([(from): 'v-2', (to): 'v-3', (T.label): 'KNOWS']).
  mergeE([(from): 'v-3', (to): 'v-4', (T.label): 'KNOWS']).
  id()
```

## Combinaison d'upserts de sommets et d'arêtes
<a name="gremlin-upserts-vertexes-and-edges"></a>

Parfois, il peut être utile d'insérer par upsert à la fois les sommets et les arêtes qui les relient. Vous pouvez combiner les exemples de lots présentés ici. L'exemple suivant insère par upsert trois sommets et deux arêtes :

```
g.mergeV([(id):'v-1']).
    option(onCreate, [(label): 'PERSON', 'email': 'person-1@example.org']).
  mergeV([(id):'v-2']).
    option(onCreate, [(label): 'PERSON', 'email': 'person-2@example.org']).
  mergeV([(id):'v-3']).
    option(onCreate, [(label): 'PERSON', 'email': 'person-3@example.org']).
  mergeE([(from): 'v-1', (to): 'v-2', (T.label): 'KNOWS']).
  mergeE([(from): 'v-2', (to): 'v-3', (T.label): 'KNOWS']).
 id()
```

## Combinaison d'upserts et d'insertions
<a name="gremlin-upserts-and-inserts"></a>

Parfois, il peut être utile d'insérer par upsert à la fois les sommets et les arêtes qui les relient. Vous pouvez combiner les exemples de lots présentés ici. L'exemple suivant insère par upsert trois sommets et deux arêtes :

Les upserts traitent généralement un élément à la fois. Si vous vous en tenez aux modèles d'upsert présentés ici, chaque opération d'upsert émet un seul traverseur, ce qui entraîne l'exécution de l'opération suivante une seule fois.

Cependant, il peut arriver que vous souhaitiez combiner des upserts avec des insertions. Cela peut notamment être le cas si vous utilisez des arêtes pour représenter des instances d'actions ou d'événements. Une demande peut utiliser des upserts pour s'assurer que tous les sommets nécessaires existent, puis utiliser des insertions pour ajouter des arêtes. Avec les demandes de ce type, soyez attentif au nombre potentiel de traverseurs émis par chaque opération.

Prenons l'exemple suivant, qui combine des upserts et des insertions pour ajouter des arêtes représentant des événements dans le graphe :

```
// Fully optimized, but inserts too many edges
g.mergeV([(id):'v-1']).
    option(onCreate, [(label): 'PERSON', 'email': 'person-1@example.org']).
  mergeV([(id):'v-2']).
    option(onCreate, [(label): 'PERSON', 'email': 'person-2@example.org']).
  mergeV([(id):'v-3']).
    option(onCreate, [(label): 'PERSON', 'email': 'person-3@example.org']).
  mergeV([(T.id): 'c-1', (T.label): 'CITY', name: 'city-1']).
  V('p-1', 'p-2').
  addE('FOLLOWED').to(V('p-1')).
  V('p-1', 'p-2', 'p-3').
  addE('VISITED').to(V('c-1')).
  id()
```

La requête doit insérer cinq arêtes : deux arêtes SUIVIES et trois arêtes VISITÉES. Cependant, la requête telle qu'elle est écrite insère huit arêtes : deux arêtes SUIVIES et six arêtes VISITÉES. Cela est dû au fait que l'opération qui insère les deux arêtes suivies émet deux traverseurs, ce qui entraîne l'exécution de l'opération suivante d'insertion de trois arêtes deux fois.

La solution consiste à ajouter une étape `fold()` après chaque opération susceptible d'émettre plusieurs traverseurs :

```
g.mergeV([(T.id): 'v-1', (T.label): 'PERSON', email: 'person-1@example.org']).
  mergeV([(T.id): 'v-2', (T.label): 'PERSON', email: 'person-2@example.org']).
  mergeV([(T.id): 'v-3', (T.label): 'PERSON', email: 'person-3@example.org']).
  mergeV([(T.id): 'c-1', (T.label): 'CITY', name: 'city-1']).
  V('p-1', 'p-2').
  addE('FOLLOWED').
    to(V('p-1')).
  fold().
  V('p-1', 'p-2', 'p-3').
  addE('VISITED').
    to(V('c-1')).
  id()
```

Nous avons inséré ici une étape `fold()` après l'opération qui insère les arêtes SUIVIES. Il en résulte un seul traverseur, et l'opération suivante n'est donc exécutée qu'une seule fois.

L'inconvénient de cette approche est que la requête n'est plus entièrement optimisée, car `fold()` n'est pas optimisé. L'opération d'insertion qui suit `fold()` ne sera maintenant pas optimisée non plus.

Si vous devez utiliser `fold()` pour réduire le nombre de traverseurs lors des étapes suivantes, essayez d'organiser les opérations de manière à ce que les moins coûteuses occupent la partie non optimisée de la requête.

## Configuration de la cardinalité
<a name="gremlin-upserts-setting-cardinality"></a>

 La cardinalité par défaut pour les propriétés des sommets dans Neptune est définie, ce qui signifie que lors de l'utilisation de mergeV (), les valeurs fournies sur la carte recevront toutes cette cardinalité. Pour utiliser la cardinalité unique, vous devez être explicite dans son utilisation. À partir de la TinkerPop version 3.7.0, une nouvelle syntaxe permet de fournir la cardinalité dans le cadre de la carte, comme indiqué dans l'exemple suivant : 

```
g.mergeV([(T.id): '1234']).
  option(onMatch, ['age': single(20), 'name': single('alice'), 'city': set('miami')])
```

 Vous pouvez également définir la cardinalité par défaut `option` comme suit : 

```
// age and name are set to single cardinality by default
g.mergeV([(T.id): '1234']).
  option(onMatch, ['age': 22, 'name': 'alice', 'city': set('boston')], single)
```

 Il existe moins d'options pour définir la cardinalité dans les versions `mergeV()` antérieures à 3.7.0. L'approche générale consiste à revenir à l'`property()`étape suivante : 

```
g.mergeV([(T.id): '1234']). 
  option(onMatch, sideEffect(property(single,'age', 20).
  property(set,'city','miami')).constant([:]))
```

**Note**  
 Cette approche ne fonctionnera que `mergeV()` si elle est utilisée avec une étape de démarrage. Vous ne pourriez donc pas `mergeV()` enchaîner une seule traversée, car la première étape utilisant cette syntaxe `mergeV()` après le début produira une erreur si le traverseur entrant est un élément graphique. Dans ce cas, vous souhaiterez diviser vos `mergeV()` appels en plusieurs demandes, chacune pouvant constituer une étape de départ. 

# Réalisation d'upserts Gremlin efficaces avec `fold()/coalesce()/unfold()`
<a name="gremlin-efficient-upserts-pre-3.6"></a>

Une insertion conditionnelle (également appelée « upsert ») réutilise un sommet ou une arête qui existe déjà, ou crée l'objet nécessaire dans le cas contraire. Des upserts efficaces peuvent faire une différence significative dans les performances des requêtes Gremlin.

Cette page montre comment utiliser le modèle Gremlin `fold()/coalesce()/unfold()` pour réaliser des upserts efficaces. Cependant, avec la sortie de la TinkerPop version 3.6.x introduite dans Neptune dans la version [1.2.1.0](engine-releases-1.2.1.0.md) du moteur, les nouvelles `mergeE()` étapes sont préférables dans la plupart `mergeV()` des cas. Le modèle `fold()/coalesce()/unfold()` décrit ici peut encore être utile dans certaines situations complexes, mais en régle générale, utilisez `mergeV()` et `mergeE()` si vous le pouvez, comme décrit dans [Réalisation d'upserts efficaces avec les étapes Gremlin `mergeV()` et `mergeE()`](gremlin-efficient-upserts.md).

Les upserts vous permettent d'écrire des opérations d'insertion idempotentes : quel que soit le nombre de fois que vous exécutez cette opération, le résultat global est le même. Cela est utile dans les scénarios d'écriture hautement simultanés où les modifications simultanées apportées à la même partie du graphe peuvent forcer une ou plusieurs transactions à revenir en arrière avec une exception `ConcurrentModificationException`, nécessitant ainsi une nouvelle tentative.

Par exemple, la requête suivante insère un sommet en recherchant d'abord le sommet spécifié dans le jeu de données, puis en regroupant les résultats dans une liste. Dans la première traversée fournie à l'étape `coalesce()`, la requête déplie ensuite cette liste. Si la liste dépliée n'est pas vide, les résultats sont émis à partir de `coalesce()`. Toutefois, si `unfold()` renvoie une collection vide parce que le sommet n'existe pas, `coalesce()` passe à l'évaluation de la deuxième traversée avec laquelle il a été fourni, et dans cette deuxième traversée, la requête crée le sommet manquant.

```
g.V('v-1').fold()
          .coalesce(
             unfold(),
             addV('Person').property(id, 'v-1')
                           .property('email', 'person-1@example.org')
           )
```

## Utilisation d'une forme optimisée de `coalesce()` pour les upserts
<a name="gremlin-upserts-pre-3.6-coalesce"></a>

Neptune peut optimiser l'idiome `fold().coalesce(unfold(), ...)` pour effectuer des mises à jour à haut débit, mais cette optimisation ne fonctionne que si les deux parties de l'idiome `coalesce()` renvoient un sommet ou une arête, mais rien d'autre. Si vous essayez de renvoyer quelque chose de différent, tel qu'une propriété, à partir de n'importe quelle partie du `coalesce()`, l'optimisation Neptune n'a pas lieu. La requête peut aboutir, mais elle ne fonctionnera pas aussi bien qu'une version optimisée, en particulier pour les vastes jeux de données.

Étant donné que les requêtes d'upsert non optimisées augmentent les temps d'exécution et réduisent le débit, il est utile d'utiliser le point de terminaison Gremlin `explain` pour déterminer si une requête d'upsert est entièrement optimisée. Lorsque vous examinez les plans `explain`, recherchez les lignes commençant par `+ not converted into Neptune steps` et `WARNING: >>`. Par exemple :

```
+ not converted into Neptune steps: [FoldStep, CoalesceStep([[UnfoldStep], [AddEdgeSte...
WARNING: >> FoldStep << is not supported natively yet
```

Ces avertissements peuvent vous aider à identifier les parties d'une requête qui empêchent son optimisation complète.

Parfois, il n'est pas possible d'optimiser complètement une requête. Dans ces situations, vous devez essayer de placer les étapes qui ne peuvent pas être optimisées à la fin de la requête, afin de permettre au moteur d'optimiser autant d'étapes que possible. Cette technique est utilisée dans certains exemples d'upserts en bloc, où tous les upserts optimisés pour un ensemble de sommets ou d'arêtes sont effectués avant que des modifications supplémentaires potentiellement non optimisées ne soient appliquées aux mêmes sommets ou arêtes.

## Exécution d'upserts par lots pour améliorer le débit
<a name="gremlin-upserts-pre-3.6-batching"></a>

Pour les scénarios d'écriture à haut débit, vous pouvez enchaîner les étapes d'upsert pour effectuer l'upsert en bloc des sommets et des arêtes. Le traitement par lots réduit la charge transactionnelle liée à l'insertion par upsert d'un grand nombre de sommets et d'arêtes. Vous pouvez ainsi améliorer davantage le débit en augmentant les demandes d'upserts par lots en parallèle à l'aide de plusieurs clients.

En règle générale, nous recommandons d'insérer par upsert environ 200 enregistrements par demande par lots. Un enregistrement correspond à une étiquette ou propriété individuelle de sommet ou d'arête. Par exemple, un sommet doté d'une seule étiquette et de quatre propriétés génère cinq enregistrements. Une arête dotée d'une étiquette et d'une seule propriété génère deux enregistrements. Si vous souhaitez insérer par upsert des lots de sommets, chacun avec une seule étiquette et quatre propriétés, vous devez commencer par une taille de lot de 40, car `200 / (1 + 4) = 40`.

Vous pouvez tester différentes tailles de lots. 200 enregistrements par lot constituent un bon point de départ, mais la taille de lot idéale peut être supérieure ou inférieure en fonction de votre charge de travail. Notez toutefois que Neptune peut limiter le nombre total d'étapes Gremlin par demande. Cette limite n'est pas documentée, mais par mesure de sécurité, essayez de faire en sorte que les demandes ne contiennent pas plus de 1 500 étapes Gremlin. Neptune peut rejeter des demandes en bloc volumineuses comportant plus de 1 500 étapes.

Pour augmenter le débit, vous pouvez insérer par upsert des lots en parallèle à l'aide de plusieurs clients (voir [Création d'écritures Gremlin multithreads efficaces](best-practices-gremlin-multithreaded-writes.md)). Le nombre de clients doit être identique au nombre de threads de travail sur votre instance Neptune Writer, qui est généralement 2 fois le nombre de v CPUs sur le serveur. Par exemple, une `r5.8xlarge` instance possède 32 V CPUs et 64 threads de travail. Pour les scénarios d'écriture à haut débit utilisant une instance `r5.8xlarge`, vous devez utiliser 64 clients écrivant des upserts par lots sur Neptune en parallèle.

Chaque client doit soumettre une demande par lots et attendre qu'elle soit terminée avant de soumettre une autre demande. Bien que les différents clients fonctionnent en parallèle, chacun d'eux soumet des demandes en série. Cela garantit que le serveur reçoit un flux constant de demandes qui occupent tous les threads de travail sans encombrer la file d'attente des demandes côté serveur (voir [Dimensionnement des instances de base de données dans un cluster de bases de données Neptune](feature-overview-db-clusters.md#feature-overview-sizing-instances)).

## Essayer d'éviter les étapes qui génèrent plusieurs traverseurs
<a name="gremlin-upserts-pre-3.6-single-traverser"></a>

Lorsqu'une étape Gremlin s'exécute, elle utilise un traverseur entrant et émet un ou plusieurs traverseurs de sortie. Le nombre de traverseurs émis par une étape détermine le nombre de fois que l'étape suivante sera exécutée.

Généralement, lorsque vous effectuez des opérations par lots, vous souhaitez que chaque opération, telle que l'upsert du sommet A, soit exécutée une seule fois, de sorte que la séquence des opérations ressemble à ceci : upsert du sommet A, puis upsert du sommet B, puis upsert du sommet C, etc. Tant qu'une étape ne crée ou ne modifie qu'un seul élément, elle n'émet qu'un seul traverseur, et les étapes représentant l'opération suivante ne sont exécutées qu'une seule fois. Si, en revanche, une opération crée ou modifie plusieurs éléments, elle émet plusieurs traverseurs, ce qui entraîne l'exécution des étapes suivantes plusieurs fois, une fois par traverseur émis. Cela peut obliger la base de données à effectuer des tâches supplémentaires inutiles et, dans certains cas, à créer des sommets, des arêtes ou des valeurs de propriétés supplémentaires superflus.

La requête `g.V().addV()` est un bon exemple de cas où la situation peut dégénérer. Cette requête simple ajoute un sommet pour chaque sommet du graphe, car `V()` émet un traverseur pour chaque sommet du graphe et chacun de ces traverseurs déclenche un appel à `addV()`.

Consultez [Combinaison d'upserts et d'insertions](#gremlin-upserts-pre-3.6-and-inserts) pour découvrir comment gérer les opérations qui peuvent émettre plusieurs traverseurs.

## Insertion de sommets par upsert
<a name="gremlin-upserts-pre-3.6-vertices"></a>

Vous pouvez utiliser un ID de sommet pour déterminer s'il existe un sommet correspondant. Il s'agit de l'approche préférée, car Neptune optimise les upserts pour les cas d'utilisation très concurrents. IDs Par exemple, la requête suivante crée un sommet avec un ID de sommet donné s'il n'existe pas déjà, ou le réutilise s'il existe déjà :

```
g.V('v-1')
 .fold()
  .coalesce(unfold(),
            addV('Person').property(id, 'v-1')
                          .property('email', 'person-1@example.org'))
  .id()
```

Notez que cette requête se termine par une étape `id()`. Bien que cela ne soit pas strictement nécessaire pour réaliser l'upsert du sommet, l'ajout d'une étape `id()` à la fin d'une requête d'upsert garantit que le serveur ne sérialise pas toutes les propriétés du sommet vers le client, ce qui contribue à réduire le coût de verrouillage de la requête.

Vous pouvez également utiliser une propriété de sommet pour déterminer si le sommet existe :

```
g.V()
 .hasLabel('Person')
 .has('email', 'person-1@example.org')
 .fold()
 .coalesce(unfold(),
           addV('Person').property('email', 'person-1@example.org'))
 .id()
```

Si possible, utilisez les sommets fournis par l'utilisateur IDs pour créer des sommets, et utilisez-les IDs pour déterminer si un sommet existe lors d'une opération de remontée. Cela permet à Neptune d'optimiser les upserts autour du. IDs Un upsert basé sur un ID peut être nettement plus efficace qu'un upsert basé sur des propriétés dans les scénarios où les modifications simultanées sont nombreuses.

### Enchaînement d'upserts de sommets
<a name="gremlin-upserts-pre-3.6-vertices-chaining"></a>

Vous pouvez enchaîner des upserts de sommets pour les insérer dans un lot :

```
g.V('v-1')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-1')
                         .property('email', 'person-1@example.org'))
 .V('v-2')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-2')
                         .property('email', 'person-2@example.org'))
 .V('v-3')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-3')
                         .property('email', 'person-3@example.org'))
 .id()
```

## Exécution d'upserts d'arêtes
<a name="gremlin-upserts-pre-3.6-edges"></a>

Vous pouvez utiliser une arête IDs pour insérer des arêtes de la même manière que vous insérez des sommets à l'aide d'un sommet personnalisé. IDs Là aussi, il s'agit de l'approche préférée, car elle permet à Neptune d'optimiser la requête. Par exemple, la requête suivante crée une arête en fonction de son ID d'arête si elle n'existe pas déjà, ou la réutilise si elle existe déjà. La requête utilise également IDs les `to` sommets `from` et si elle doit créer une nouvelle arête.

```
g.E('e-1')
 .fold()
 .coalesce(unfold(),
           addE('KNOWS').from(V('v-1'))
                        .to(V('v-2'))
                        .property(id, 'e-1'))
 .id()
```

De nombreuses applications utilisent un sommet personnalisé IDs, mais laissent à Neptune le soin de générer l'arête. IDs Si vous ne connaissez pas l'identifiant d'une arête, mais que vous connaissez le `to` sommet `from` et IDs, vous pouvez utiliser cette formulation pour surdimensionner une arête :

```
g.V('v-1')
 .outE('KNOWS')
 .where(inV().hasId('v-2'))
 .fold()
 .coalesce(unfold(),
           addE('KNOWS').from(V('v-1'))
                        .to(V('v-2')))
 .id()
```

Notez que l'étape du sommet dans la clause `where()` doit être `inV()` (ou `outV()` si vous avez utilisé `inE()` pour trouver l'arête), non pas `otherV()`. N'utilisez pas `otherV()` ici. Dans le cas contraire, la requête ne sera pas optimisée, et les performances en pâtiront. Par exemple, Neptune n'optimiserait pas la requête suivante :

```
// Unoptimized upsert, because of otherV()
g.V('v-1')
 .outE('KNOWS')
 .where(otherV().hasId('v-2'))
 .fold()
 .coalesce(unfold(),
           addE('KNOWS').from(V('v-1'))
                        .to(V('v-2')))
 .id()
```

Si vous ne connaissez pas l'arête ou le sommet situé IDs à l'avant, vous pouvez l'inverser à l'aide des propriétés du sommet :

```
g.V()
 .hasLabel('Person')
 .has('name', 'person-1')
 .outE('LIVES_IN')
 .where(inV().hasLabel('City').has('name', 'city-1'))
 .fold()
 .coalesce(unfold(),
           addE('LIVES_IN').from(V().hasLabel('Person')
                                    .has('name', 'person-1'))
                           .to(V().hasLabel('City')
                                  .has('name', 'city-1')))
 .id()
```

Comme pour les points ascendants, il est préférable d'utiliser des éléments ascendants basés sur un identifiant d'arête ou un `to` sommet IDs, plutôt que des points ascendants basés sur `from` des propriétés, afin que Neptune puisse optimiser pleinement l'upsert.

### Vérification de l'existence de sommets `from` et `to`
<a name="gremlin-upserts-pre-3.6-edges-checking"></a>

Notez la structure des étapes qui créent une arête : `addE().from().to()`. Cette structure garantit que la requête vérifie l'existence à la fois du sommet `from` et du sommet `to`. S'ils n'existent pas, la requête renvoie le message d'erreur suivant :

```
{
  "detailedMessage": "Encountered a traverser that does not map to a value for child...
  "code": "IllegalArgumentException",
  "requestId": "..."
}
```

S'il est possible que le sommet `from` ou `to` n'existe pas, vous devez essayer de les placer par upsert avant de réaliser l'upsert de l'arête qui les sépare. Consultez [Combinaison d'upserts de sommets et d'arêtes](#gremlin-upserts-pre-3.6-vertexes-and-edges).

Une autre structure permet de créer une arête que vous ne devez pas utiliser : `V().addE().to()`. Elle ajoute une arête uniquement si le sommet `from` existe. Si le sommet `to` n'existe pas, la requête génère une erreur, comme décrit précédemment, mais si le sommet `from` n'existe pas, l'upsert de l'arête échoue en arrière-plan, sans générer d'erreur. Par exemple, si le sommet `from` n'existe pas, l'upsert suivant a lieu sans effectuer l'upsert d'une arête :

```
// Will not insert edge if from vertex does not exist
g.V('v-1')
 .outE('KNOWS')
 .where(inV().hasId('v-2'))
 .fold()
 .coalesce(unfold(),
           V('v-1').addE('KNOWS')
                   .to(V('v-2')))
 .id()
```

### Enchaînement d'upserts d'arêtes
<a name="gremlin-upserts-pre-3.6-edges-chaining"></a>

Si vous souhaitez enchaîner des points d'arête pour créer une demande par lots, vous devez commencer chaque insertion par une recherche de sommet, même si vous connaissez déjà l'arête. IDs

Si vous connaissez déjà les IDs arêtes que vous souhaitez insérer, ainsi que les IDs `to` sommets `from` et, vous pouvez utiliser cette formulation :

```
g.V('v-1')
 .outE('KNOWS')
 .hasId('e-1')
 .fold()
 .coalesce(unfold(),
           V('v-1').addE('KNOWS')
                   .to(V('v-2'))
                   .property(id, 'e-1'))
 .V('v-3')
 .outE('KNOWS')
 .hasId('e-2').fold()
 .coalesce(unfold(),
           V('v-3').addE('KNOWS')
                   .to(V('v-4'))
                   .property(id, 'e-2'))
 .V('v-5')
 .outE('KNOWS')
 .hasId('e-3')
 .fold()
 .coalesce(unfold(),
           V('v-5').addE('KNOWS')
                   .to(V('v-6'))
                   .property(id, 'e-3'))
 .id()
```

Le scénario d'inversion d'arêtes par lots le plus courant est peut-être que vous connaissez le `to` sommet `from` et IDs, mais que vous ne connaissez pas les IDs arêtes que vous souhaitez inverser. Dans ce cas, utilisez la formulation suivante :

```
g.V('v-1')
 .outE('KNOWS')
 .where(inV().hasId('v-2'))
 .fold()
 .coalesce(unfold(),
           V('v-1').addE('KNOWS')
                   .to(V('v-2')))

 .V('v-3')
 .outE('KNOWS')
 .where(inV().hasId('v-4'))
 .fold()
 .coalesce(unfold(),
           V('v-3').addE('KNOWS')
                   .to(V('v-4')))
 .V('v-5')
 .outE('KNOWS')
 .where(inV().hasId('v-6'))
 .fold()
 .coalesce(unfold(),
           V('v-5').addE('KNOWS').to(V('v-6')))
 .id()
```

Si vous connaissez IDs les arêtes que vous souhaitez insérer, mais que vous ne connaissez pas les IDs `to` sommets `from` et les sommets (c'est inhabituel), vous pouvez utiliser cette formulation :

```
g.V()
 .hasLabel('Person')
 .has('email', 'person-1@example.org')
 .outE('KNOWS')
 .hasId('e-1')
 .fold()
 .coalesce(unfold(),
           V().hasLabel('Person')
              .has('email', 'person-1@example.org')
              .addE('KNOWS')
              .to(V().hasLabel('Person')
                     .has('email', 'person-2@example.org'))
                     .property(id, 'e-1'))
 .V()
 .hasLabel('Person')
 .has('email', 'person-3@example.org')
 .outE('KNOWS')
 .hasId('e-2')
 .fold()
 .coalesce(unfold(),
           V().hasLabel('Person')
              .has('email', 'person-3@example.org')
              .addE('KNOWS')
              .to(V().hasLabel('Person')
                     .has('email', 'person-4@example.org'))
              .property(id, 'e-2'))
 .V()
 .hasLabel('Person')
 .has('email', 'person-5@example.org')
 .outE('KNOWS')
 .hasId('e-1')
 .fold()
 .coalesce(unfold(),
           V().hasLabel('Person')
              .has('email', 'person-5@example.org')
              .addE('KNOWS')
              .to(V().hasLabel('Person')
                     .has('email', 'person-6@example.org'))
                     .property(id, 'e-3'))
 .id()
```

## Combinaison d'upserts de sommets et d'arêtes
<a name="gremlin-upserts-pre-3.6-vertexes-and-edges"></a>

Parfois, il peut être utile d'insérer par upsert à la fois les sommets et les arêtes qui les relient. Vous pouvez combiner les exemples de lots présentés ici. L'exemple suivant insère par upsert trois sommets et deux arêtes :

```
g.V('p-1')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'p-1')
                         .property('email', 'person-1@example.org'))
 .V('p-2')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'p-2')
                         .property('name', 'person-2@example.org'))
 .V('c-1')
 .fold()
 .coalesce(unfold(),
           addV('City').property(id, 'c-1')
                       .property('name', 'city-1'))
 .V('p-1')
 .outE('LIVES_IN')
 .where(inV().hasId('c-1'))
 .fold()
 .coalesce(unfold(),
           V('p-1').addE('LIVES_IN')
                   .to(V('c-1')))
 .V('p-2')
 .outE('LIVES_IN')
 .where(inV().hasId('c-1'))
 .fold()
 .coalesce(unfold(),
           V('p-2').addE('LIVES_IN')
                   .to(V('c-1')))
 .id()
```

## Combinaison d'upserts et d'insertions
<a name="gremlin-upserts-pre-3.6-and-inserts"></a>

Parfois, il peut être utile d'insérer par upsert à la fois les sommets et les arêtes qui les relient. Vous pouvez combiner les exemples de lots présentés ici. L'exemple suivant insère par upsert trois sommets et deux arêtes :

Les upserts traitent généralement un élément à la fois. Si vous vous en tenez aux modèles d'upsert présentés ici, chaque opération d'upsert émet un seul traverseur, ce qui entraîne l'exécution de l'opération suivante une seule fois.

Cependant, il peut arriver que vous souhaitiez combiner des upserts avec des insertions. Cela peut notamment être le cas si vous utilisez des arêtes pour représenter des instances d'actions ou d'événements. Une demande peut utiliser des upserts pour s'assurer que tous les sommets nécessaires existent, puis utiliser des insertions pour ajouter des arêtes. Avec les demandes de ce type, soyez attentif au nombre potentiel de traverseurs émis par chaque opération.

Prenons l'exemple suivant, qui combine des upserts et des insertions pour ajouter des arêtes représentant des événements dans le graphe :

```
// Fully optimized, but inserts too many edges
g.V('p-1')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'p-1')
                         .property('email', 'person-1@example.org'))
 .V('p-2')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'p-2')
                         .property('name', 'person-2@example.org'))
 .V('p-3')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'p-3')
                         .property('name', 'person-3@example.org'))
 .V('c-1')
 .fold()
 .coalesce(unfold(),
           addV('City').property(id, 'c-1')
                       .property('name', 'city-1'))
 .V('p-1', 'p-2')
 .addE('FOLLOWED')
 .to(V('p-1'))
 .V('p-1', 'p-2', 'p-3')
 .addE('VISITED')
 .to(V('c-1'))
 .id()
```

La requête doit insérer cinq arêtes : deux arêtes SUIVIES et trois arêtes VISITÉES. Cependant, la requête telle qu'elle est écrite insère huit arêtes : deux arêtes SUIVIES et six arêtes VISITÉES. Cela est dû au fait que l'opération qui insère les deux arêtes suivies émet deux traverseurs, ce qui entraîne l'exécution de l'opération suivante d'insertion de trois arêtes deux fois.

La solution consiste à ajouter une étape `fold()` après chaque opération susceptible d'émettre plusieurs traverseurs :

```
g.V('p-1')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'p-1')
                         .property('email', 'person-1@example.org'))
 .V('p-2')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'p-2').
                         .property('name', 'person-2@example.org'))
 .V('p-3')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'p-3').
                         .property('name', 'person-3@example.org'))
 .V('c-1')
 .fold().
 .coalesce(unfold(),
            addV('City').property(id, 'c-1').
                        .property('name', 'city-1'))
 .V('p-1', 'p-2')
 .addE('FOLLOWED')
 .to(V('p-1'))
 .fold()
 .V('p-1', 'p-2', 'p-3')
 .addE('VISITED')
 .to(V('c-1')).
 .id()
```

Nous avons inséré ici une étape `fold()` après l'opération qui insère les arêtes SUIVIES. Il en résulte un seul traverseur, et l'opération suivante n'est donc exécutée qu'une seule fois.

L'inconvénient de cette approche est que la requête n'est plus entièrement optimisée, car `fold()` n'est pas optimisé. L'opération d'insertion qui suit `fold()` ne sera maintenant pas optimisée non plus.

Si vous devez utiliser `fold()` pour réduire le nombre de traverseurs lors des étapes suivantes, essayez d'organiser les opérations de manière à ce que les moins coûteuses occupent la partie non optimisée de la requête.

## Upserts qui modifient les sommets et les arêtes existants
<a name="gremlin-upserts-pre-3.6-that-modify"></a>

Parfois, vous souhaitez créer un sommet ou une arête qui n'existe pas, puis y ajouter une propriété ou mettre à jour une propriété qui lui est associée, qu'il s'agisse d'un sommet ou d'une arête qui existe déjà ou pas encore.

Pour ajouter ou modifier une propriété, utilisez l'étape `property()`. Utilisez cette étape en dehors de l'étape `coalesce()`. Si vous essayez de modifier la propriété d'un sommet ou d'une arête qui existe déjà dans l'étape `coalesce()`, il est possible que la requête ne soit pas optimisée par le moteur de requêtes Neptune.

La requête suivante ajoute ou met à jour une propriété de compteur sur chaque sommet faisant l'objet d'un upsert. Chaque étape `property()` possède une cardinalité unique afin de garantir que les nouvelles valeurs remplacent toutes les valeurs existantes, plutôt que d'être ajoutées à un ensemble de valeurs existantes.

```
g.V('v-1')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-1')
                         .property('email', 'person-1@example.org'))
 .property(single, 'counter', 1)
 .V('v-2')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-2')
                         .property('email', 'person-2@example.org'))
 .property(single, 'counter', 2)
 .V('v-3')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-3')
                         .property('email', 'person-3@example.org'))
 .property(single, 'counter', 3)
 .id()
```

Si vous avez une valeur de propriété, telle qu'une valeur d'horodatage `lastUpdated`, qui s'applique à tous les éléments ajoutés par upsert, vous pouvez l'ajouter ou la mettre à jour à la fin de la requête :

```
g.V('v-1')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-1')
                         .property('email', 'person-1@example.org'))
 .V('v-2').
 .fold().
 .coalesce(unfold(),
           addV('Person').property(id, 'v-2')
                         .property('email', 'person-2@example.org'))
 .V('v-3')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-3')
                         .property('email', 'person-3@example.org'))
 .V('v-1', 'v-2', 'v-3')
 .property(single, 'lastUpdated', datetime('2020-02-08'))
 .id()
```

Si d'autres conditions déterminent si un sommet ou une arête doit être encore modifié, vous pouvez utiliser une étape `has()` pour filtrer les éléments auxquels une modification sera appliquée. L'exemple suivant utilise une étape `has()` pour filtrer les sommets ajoutés par upsert en fonction de la valeur de leur propriété `version`. La requête fait ainsi passer à 3 la `version` de tout sommet dont l'élément `version` est inférieur à 3 :

```
g.V('v-1')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-1')
                         .property('email', 'person-1@example.org')
                         .property('version', 3))
 .V('v-2')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-2')
                         .property('email', 'person-2@example.org')
                         .property('version', 3))
 .V('v-3')
 .fold()
 .coalesce(unfold(),
           addV('Person').property(id, 'v-3')
                         .property('email', 'person-3@example.org')
                         .property('version', 3))
 .V('v-1', 'v-2', 'v-3')
 .has('version', lt(3))
 .property(single, 'version', 3)
 .id()
```

# Analyse de l'exécution des requêtes à l'aide de Gremlin `explain`
<a name="gremlin-explain"></a>

Amazon Neptune a ajouté une fonctionnalité Gremlin nommée *explain*. Cette fonctionnalité est un outil en libre-service qui vous aide à comprendre l'approche d'exécution adoptée par le moteur Neptune. Vous l'appelez en ajoutant un paramètre `explain` à un appel HTTP qui soumet une requête Gremlin.

La fonction `explain` fournit des informations sur la structure logique des plans d'exécution de requête. Vous pouvez utiliser ces informations pour identifier les goulots d'étranglement potentiels liés à l'évaluation et à l'exécution, comme expliqué dans [Réglage des requêtes Gremlin](gremlin-traversal-tuning.md). Vous pouvez aussi utiliser des [indicateurs de requête](gremlin-query-hints.md) pour améliorer les plans d'exécution de requêtes.

**Topics**
+ [Présentation du fonctionnement des requêtes Gremlin dans Neptune](gremlin-explain-background.md)
+ [Utilisation de l'API Gremlin `explain` dans Neptune](gremlin-explain-api.md)
+ [API Gremlin `profile` dans Neptune](gremlin-profile-api.md)
+ [Réglage des requêtes Gremlin à l'aide d'`explain` et de `profile`](gremlin-traversal-tuning.md)
+ [Prise en charge des étapes Gremlin natives dans Amazon Neptune](gremlin-step-support.md)

# Présentation du fonctionnement des requêtes Gremlin dans Neptune
<a name="gremlin-explain-background"></a>

Pour tirer pleinement parti des rapports Gremlin `explain` et `profile` dans Amazon Neptune, il est utile de comprendre certaines informations contextuelles sur les requêtes Gremlin.

**Topics**
+ [Déclarations Gremlin dans Neptune](gremlin-explain-background-statements.md)
+ [Comment Neptune traite les requêtes Gremlin à l'aide d'index d'instruction](gremlin-explain-background-indexing-examples.md)
+ [Traitement des requêtes Gremlin dans Neptune](gremlin-explain-background-querying.md)

# Déclarations Gremlin dans Neptune
<a name="gremlin-explain-background-statements"></a>

Les données de graphe de propriétés d'Amazon Neptune sont composées de déclarations à quatre positions (quadruplets). Chacune de ces instructions représente une unité atomique individuelle des données de graphe de propriété. Pour de plus amples informations, veuillez consulter [Modèle de données de graphe de Neptune](feature-overview-data-model.md). À l'instar du modèle de données RDF (Resource Description Framework), ces quatre positions sont les suivantes :
+ `subject (S)`
+ `predicate (P)`
+ `object (O)`
+ `graph (G)`

Chaque instruction est une assertion sur une ou plusieurs ressources. Par exemple, une instruction peut déclarer l'existence d'une relation entre deux ressources ou attacher une propriété (paire clé/valeur) à une ressource.

Vous pouvez considérer la position de prédicat (predicate) comme le verbe de l'instruction, qui décrit le type de relation ou de propriété. L'objet est la cible de la relation ou la valeur de la propriété. La position du graphe est facultative et peut être utilisée de nombreuses manières. Pour les données de graphe de propriétés (PG), elle est soit inutilisée (graphe null), soit utilisée pour représenter l'identifiant d'une arête. Un graphe est constitué d'un ensemble de déclarations avec des identifiants de ressources partagées.

Il existe trois classes de déclarations dans le modèle de données de graphe de propriétés Neptune :

**Topics**
+ [Instructions d'étiquette de sommet](#gremlin-explain-background-vertex-labels)
+ [Instructions d'arc](#gremlin-explain-background-edge-statements)
+ [Instructions de propriété](#gremlin-explain-background-property-statements)

## Instructions d'étiquette de sommet Gremlin
<a name="gremlin-explain-background-vertex-labels"></a>

Les déclarations d'étiquette de sommet dans Neptune ont deux objectifs :
+ Elles permettent d'assurer le suivi des étiquettes d'un sommet.
+ La présence d'au moins une de ces instructions implique l'existence d'un sommet particulier dans le graphe.

Le sujet de ces instructions est un identifiant de sommet et l'objet est une étiquette, ces deux éléments étant spécifiés par l'utilisateur. Vous utilisez un prédicat fixe spécial pour ces instructions, affiché sous la forme `<~label>`, et un identifiant de graphe par défaut (graphe null), affiché sous la forme `<~>`.

Considérons par exemple la traversée `addV` suivante.

```
g.addV("Person").property(id, "v1")
```

Cette traversée entraîne l'ajout de l'instruction suivante au graphe.

```
StatementEvent[Added(<v1> <~label> <Person> <~>) .]
```

## Instructions d'arc Gremlin
<a name="gremlin-explain-background-edge-statements"></a>

Une déclaration d'arête Gremlin implique l'existence d'une arête entre deux sommets dans un graphe dans Neptune. Le sujet (S) d'une instruction d'arc est le sommet source `from`. Le prédicat (P) est une étiquette d'arc fournie par l'utilisateur. L'objet (O) est le sommet cible `to`. Le graphe (G) est un identifiant d'arc fourni par l'utilisateur.

Considérons par exemple la traversée `addE` suivante.

```
g.addE("knows").from(V("v1")).to(V("v2")).property(id, "e1")
```

La traversée se traduit par l'ajout de l'instruction suivante au graphe.

```
StatementEvent[Added(<v1> <knows> <v2> <e1>) .]
```

## Instructions de propriété Gremlin
<a name="gremlin-explain-background-property-statements"></a>

Une déclaration de propriété Gremlin dans Neptune définit une valeur de propriété individuelle pour un sommet ou une arête. Le sujet est un identifiant d'arc ou de sommet fourni par l'utilisateur. Le prédicat est le nom de propriété (clé) et l'objet est la valeur de propriété individuelle. Le graphe (G) est à nouveau l'identifiant de graphe par défaut, le graphe null, affiché sous la forme `<~>`.

Prenons l'exemple de propriété de sommet suivant.

```
g.V("v1").property("name", "John")
```

Cette instruction aboutit aux résultats suivants.

```
StatementEvent[Added(<v1> <name> "John" <~>) .]
```

Les instructions de propriété diffèrent des autres en ce sens que leur objet est une valeur primitive (`string`, `date`, `byte`, `short`, `int`, `long`, `float` ou `double`). Leur objet n'est pas un identifiant de ressource pouvant être utilisé comme sujet d'une autre assertion.

Dans le cas de propriétés multiples, chaque valeur de propriété individuelle de l'ensemble reçoit sa propre instruction.

```
g.V("v1").property(set, "phone", "956-424-2563").property(set, "phone", "956-354-3692 (tel:9563543692)")
```

La sortie obtenue est la suivante.

```
StatementEvent[Added(<v1> <phone> "956-424-2563" <~>) .]
StatementEvent[Added(<v1> <phone> "956-354-3692" <~>) .]
```

Les propriétés des arêtes sont gérées de la même manière que les propriétés des sommets, mais elles utilisent l'identifiant de bord en position (S). Par exemple, ajouter une propriété à une arête :

```
g.E("e1").property("weight", 0.8)
```

Cela entraîne l'ajout de l'instruction suivante au graphique.

```
StatementEvent[Added(<e1> <weight> 0.8 <~>) .]
```

# Comment Neptune traite les requêtes Gremlin à l'aide d'index d'instruction
<a name="gremlin-explain-background-indexing-examples"></a>

Les instructions sont accessibles dans Amazon Neptune au moyen de trois index d'instruction, comme indiqué dans [Comment les instructions sont indexées dans Neptune](feature-overview-storage-indexing.md). Neptune extrait un *modèle* d'instruction à partir d'une requête Gremlin dans laquelle certaines positions sont connues, tandis que les autres peuvent être découvertes via une recherche par index.

Neptune présume que le schéma de graphe de propriétés est de petite taille. Par conséquent, le nombre d'étiquettes d'arête et de noms de propriété distincts est relativement faible, ce qui se traduit par un faible nombre total de prédicats distincts. Neptune suit les prédicats distincts dans un index séparé. Il utilise ce cache de prédicats pour effectuer une analyse d'union de `{ all P x POGS }` au lieu d'utiliser un index OSGP. Le fait d'éviter d'avoir besoin d'un index OSGP de traversée inverse permet d'économiser de l'espace de stockage et du débit de charge.

L' Explain/Profile API Neptune Gkremlin vous permet d'obtenir le nombre de prédicats dans votre graphique. Vous pouvez ensuite déterminer si votre application invalide l'hypothèse Neptune selon laquelle le schéma de votre graphe de propriété est de petite taille.

Les exemples suivants illustrent la façon dont Neptune utilise les index pour traiter les requêtes Gremlin.

**Question : Quelles sont les étiquettes du sommet `v1` ?**

```
  Gremlin code:      g.V('v1').label()
  Pattern:           (<v1>, <~label>, ?, ?)
  Known positions:   SP
  Lookup positions:  OG
  Index:             SPOG
  Key range:         <v1>:<~label>:*
```

**Question : Quelles sont les arêtes sortantes « knows » du sommet `v1` ?**

```
  Gremlin code:      g.V('v1').out('knows')
  Pattern:           (<v1>, <knows>, ?, ?)
  Known positions:   SP
  Lookup positions:  OG
  Index:             SPOG
  Key range:         <v1>:<knows>:*
```

**Question : Quels sont les sommets qui ont une étiquette de sommet `Person` ?**

```
  Gremlin code:      g.V().hasLabel('Person')
  Pattern:           (?, <~label>, <Person>, <~>)
  Known positions:   POG
  Lookup positions:  S
  Index:             POGS
  Key range:         <~label>:<Person>:<~>:*
```

**Question : Quels sont les from/to sommets d'une arête donnée ? `e1`**

```
  Gremlin code:      g.E('e1').bothV()
  Pattern:           (?, ?, ?, <e1>)
  Known positions:   G
  Lookup positions:  SPO
  Index:             GPSO
  Key range:         <e1>:*
```

Neptune **ne possède pas** d'index de déclarations tel qu'un index OSGP de traversée inverse. Ce type d'index peut être utilisé pour collecter toutes les arêtes entrantes sur toutes les étiquettes d'arête, comme dans l'exemple suivant.

**Question : Quels sont les sommets adjacents entrants `v1` ?**

```
  Gremlin code:      g.V('v1').in()
  Pattern:           (?, ?, <v1>, ?)
  Known positions:   O
  Lookup positions:  SPG
  Index:             OSGP  // <-- Index does not exist
```

# Traitement des requêtes Gremlin dans Neptune
<a name="gremlin-explain-background-querying"></a>

Dans Amazon Neptune, les traversées plus complexes peuvent être représentées par une série de modèles qui créent une relation basée sur la définition de variables nommées pouvant être partagées entre des modèles pour créer des jointures. Voici un exemple :

**Question : Quel est le voisinage à deux sauts du sommet `v1` ?**

```
  Gremlin code:      g.V(‘v1’).out('knows').out('knows').path()
  Pattern:           (?1=<v1>, <knows>, ?2, ?) X Pattern(?2, <knows>, ?3, ?)

  The pattern produces a three-column relation (?1, ?2, ?3) like this:
                     ?1     ?2     ?3
                     ================
                     v1     v2     v3
                     v1     v2     v4
                     v1     v5     v6
```

En partageant la variable `?2` entre les deux modèles (à la position O dans le premier modèle et à la position S dans le second modèle), vous créez une jointure entre les voisins à un premier saut et les voisins à deux sauts. Chaque solution Neptune possède des liaisons pour les trois variables nommées, qui peuvent être utilisées pour recréer un [TinkerPopTraverser](http://tinkerpop.apache.org/docs/current/reference/#_the_traverser) (y compris les informations de chemin).

```
```

[La première étape du traitement des requêtes Gkremlin consiste à analyser la requête pour en faire un objet TinkerPop [Traversal](http://tinkerpop.apache.org/docs/current/reference/#traversal), composé d'une série d'étapes. TinkerPop ](http://tinkerpop.apache.org/docs/current/reference/#graph-traversal-steps) Ces étapes, qui font partie du [ TinkerPop projet open source Apache](http://tinkerpop.apache.org/), sont à la fois les opérateurs logiques et physiques qui composent une traversée Gremlin dans l'implémentation de référence. Elles sont toutes deux utilisées pour représenter le modèle de la requête. Il s'agit d'opérateurs exécutables qui peuvent produire des solutions en fonction de la sémantique de l'opérateur qu'ils représentent. Par exemple, `.V()` est à la fois représenté et exécuté par le TinkerPop [GraphStep](http://tinkerpop.apache.org/docs/current/reference/#graph-step).

Ces off-the-shelf TinkerPop étapes étant exécutables, un tel TinkerPop Traversal peut exécuter n'importe quelle requête Gremlin et produire la bonne réponse. Cependant, lorsqu'elles sont exécutées sur un graphique de grande taille, TinkerPop les étapes peuvent parfois être très inefficaces et lentes. Au lieu de les utiliser, Neptune essaie alors de convertir la traversée en forme déclarative composée de groupes de modèles, comme décrit précédemment.

Neptune ne prend actuellement pas en charge tous les opérateurs Gremlin (étapes) dans son moteur de requête natif. Il essaie donc de réduire autant d'étapes que possible en une seule étape `NeptuneGraphQueryStep`, qui contient le plan de requête logique déclaratif pour toutes les étapes qui ont été converties. Idéalement, toutes les étapes sont converties. Mais lorsqu'une étape ne peut pas être convertie, Neptune sort de l'exécution native et reporte l'exécution de toutes les requêtes à partir de ce point jusqu'aux étapes. TinkerPop Il n'essaie pas de jongler avec et sans l'exécution native.

Une fois que les étapes sont converties en plan de requête logique, Neptune exécute une série d'optimiseurs de requête qui réécrivent le plan de requête en fonction de l'analyse statique et des cardinalités estimées. Ces optimiseurs effectuent des opérations telles que la réorganisation des opérateurs en fonction du nombre de plages, la suppression des opérateurs superflus ou redondants, la réorganisation des filtres, le transfert des opérateurs dans différents groupes, etc.

Une fois qu'un plan de requête optimisé est généré, Neptune crée un pipeline d'opérateurs physiques qui effectuent le travail d'exécution de la requête. Cela inclut la lecture des données à partir des index d'instruction, l'exécution de jointures de différents types, le filtrage, l'organisation, etc. Le pipeline produit un flux de solution qui est ensuite reconverti en un flux d'objets TinkerPop Traverser.

## Sérialisation des résultats de requête
<a name="gremlin-explain-background-querying-serialization"></a>

Amazon Neptune s'appuie actuellement sur les sérialiseurs de messages de TinkerPop réponse pour convertir les résultats des requêtes (TinkerPop Traversers) en données sérialisées à renvoyer par câble au client. Ces formats de sérialisation ont tendance à être assez verbeux.

Par exemple, pour sérialiser le résultat d'une requête de sommet telle que `g.V().limit(1)`, le moteur de requête Neptune doit effectuer une seule recherche pour générer le résultat. Toutefois, le sérialiseur `GraphSON` effectue un grand nombre de recherches supplémentaires pour empaqueter le sommet dans le format de sérialisation. Il doit effectuer une recherche pour obtenir l'étiquette, une recherche pour obtenir les clés de propriété et une recherche par clé de propriété pour que le sommet puisse obtenir toutes les valeurs de chaque clé.

Certains formats de sérialisation sont plus efficaces, mais tous nécessitent des recherches supplémentaires. De plus, les TinkerPop sérialiseurs n'essaient pas d'éviter les recherches dupliquées, ce qui entraîne souvent la répétition inutile de nombreuses recherches.

Il est donc très important d'écrire vos requêtes afin qu'elles demandent spécifiquement les informations dont elles ont besoin. Par exemple, `g.V().limit(1).id()` renvoie uniquement l'ID de sommet et élimine toutes les recherches de sérialiseur supplémentaires. L'[API Gremlin `profile` dans Neptune](gremlin-profile-api.md) vous permet de voir combien d'appels de recherche sont effectués pendant l'exécution de la requête et pendant la sérialisation.

# Utilisation de l'API Gremlin `explain` dans Neptune
<a name="gremlin-explain-api"></a>

L'API Amazon Neptune Gremlin `explain` renvoie le plan de requête qui serait exécuté si une requête spécifique était exécutée. Comme l'API n'exécute pas réellement la requête, le plan est renvoyé presque instantanément.

Elle diffère de l'étape TinkerPop .explain () afin de pouvoir rapporter des informations spécifiques au moteur Neptune.

## Informations qui se trouvent dans un rapport Gremlin `explain`
<a name="gremlin-explain-api-results"></a>

Un rapport `explain` contient les informations suivantes :
+ Chaîne de requête demandée.
+ **Traversée d'origine.** Il s'agit de l'objet TinkerPop Traversal produit en analysant la chaîne de requête en TinkerPop étapes. Elle est équivalente à la requête d'origine produite en exécutant la requête `.explain()` sur le TinkerPop TinkerGraph.
+ **Traversée convertie.** Il s'agit du Neptune Traversal produit en convertissant le TinkerPop Traversal en représentation logique du plan de requêtes Neptune. Dans de nombreux cas, l'intégralité de la TinkerPop traversée est convertie en deux étapes Neptune : l'une qui exécute la requête complète `NeptuneGraphQueryStep` () et l'autre qui reconvertit la sortie du moteur de requêtes Neptune en Traversers (). TinkerPop `NeptuneTraverserConverterStep`
+ **Traversée optimisée.** Il s'agit de la version optimisée du plan de requête Neptune une fois qu'il a été exécuté via une série d'optimiseurs statiques de réduction du travail qui réécrivent la requête en fonction de l'analyse statique et des cardinalités estimées. Ces optimiseurs effectuent des opérations telles que la réorganisation des opérateurs en fonction du nombre de plages, la suppression des opérateurs superflus ou redondants, la réorganisation des filtres, le transfert des opérateurs dans différents groupes, etc.
+ **Nombre de prédicats.** En raison de la stratégie d'indexation Neptune décrite précédemment, le fait d'avoir un grand nombre de prédicats différents peut entraîner des problèmes de performances. Cela est particulièrement vrai pour les requêtes qui utilisent des opérateurs de traversée inverse sans étiquette d'arc (`.in` ou `.both`). Si ces opérateurs sont utilisés et que le nombre de prédicats est suffisamment élevé, le rapport `explain` affiche un message d'avertissement.
+ **Informations DFE.** Lorsque le moteur alternatif DFE est activé, les composants de traversée suivants peuvent apparaître dans la traversée optimisée :
  + **`DFEStep`** : étape DFE optimisée pour Neptune dans la traversée qui contient un objet `DFENode` enfant. `DFEStep` représente la partie du plan de requête exécutée dans le moteur DFE.
  + **`DFENode`** : contient la représentation intermédiaire sous la forme d'un ou de plusieurs objets `DFEJoinGroupNodes` enfants.
  + **`DFEJoinGroupNode`** : représente une jointure d'un ou de plusieurs éléments `DFENode` ou `DFEJoinGroupNode`.
  + **`NeptuneInterleavingStep`** : étape DFE optimisée pour Neptune dans la traversée qui contient un objet `DFEStep` enfant.

    Contient également un élément `stepInfo` comportant des informations sur la traversée, telles que l'élément frontière, les éléments de chemin utilisés, etc. Ces informations sont utilisées pour traiter l'objet `DFEStep` enfant.

  Un moyen simple de savoir si votre requête est évaluée par le DFE est de vérifier si la sortie `explain` contient un objet `DFEStep`. Toute partie de la traversée qui n'en fait pas partie ne `DFEStep` sera pas exécutée par DFE et sera exécutée par le TinkerPop moteur.

  Consultez [Exemple avec le DFE activé](#gremlin-explain-dfe) pour voir un exemple de rapport.

## Syntaxe Gremlin `explain`
<a name="gremlin-explain-api-syntax"></a>

La syntaxe de l'API `explain` est identique à celle de l'API HTTP de la requête, sauf qu'elle utilise `/gremlin/explain` comme point de terminaison au lieu de `/gremlin`, comme dans l'exemple suivant.

```
curl -X POST https://your-neptune-endpoint:port/gremlin/explain -d '{"gremlin":"g.V().limit(1)"}'
```

La requête précédente génèrerait la sortie suivante.

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============
g.V().limit(1)

Original Traversal
==================
[GraphStep(vertex,[]), RangeGlobalStep(0,1)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
        }, finishers=[limit(1)], annotations={path=[Vertex(?1):GraphStep], maxVarId=3}
    },
    NeptuneTraverserConverterStep
]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .], {estimatedCardinality=INFINITY}
        }, finishers=[limit(1)], annotations={path=[Vertex(?1):GraphStep], maxVarId=3}
    },
    NeptuneTraverserConverterStep
]

Predicates
==========
# of predicates: 18
```

## Étapes non converties TinkerPop
<a name="gremlin-explain-unconverted-steps"></a>

Idéalement, toutes les TinkerPop étapes d'une traversée bénéficient d'une couverture native de l'opérateur Neptune. Lorsque ce n'est pas le cas, Neptune recourt à l'exécution par TinkerPop étapes pour combler les lacunes dans la couverture de ses opérateurs. Si une traversée utilise une étape pour laquelle Neptune n'a pas encore de couverture native, le rapport `explain` affiche un avertissement indiquant où l'écart s'est produit.

Lorsqu'une étape sans opérateur Neptune natif correspondant est rencontrée, la totalité de la traversée à partir de ce point est exécutée par TinkerPop étapes, même si les étapes suivantes comportent des opérateurs Neptune natifs.

L'exception est lorsque la recherche en texte intégral Neptune est appelée. Il NeptuneSearchStep implémente des étapes sans équivalents natifs sous forme d'étapes de recherche en texte intégral.

## Exemple de sortie `explain` où toutes les étapes d'une requête ont des équivalents natifs
<a name="gremlin-explain-all-steps-converted"></a>

Voici un exemple de rapport `explain` concernant une requête pour laquelle toutes les étapes ont des équivalents natifs :

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============
g.V().out()

Original Traversal
==================
[GraphStep(vertex,[]), VertexStep(OUT,vertex)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
            PatternNode[(?1, ?5, ?3, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .]
            PatternNode[(?3, <~label>, ?4, <~>) . project ask .]
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep], maxVarId=7}
    },
    NeptuneTraverserConverterStep
]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, ?5, ?3, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=INFINITY}
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep], maxVarId=7}
    },
    NeptuneTraverserConverterStep
]

Predicates
==========
# of predicates: 18
```

## Exemple où certaines étapes d'une requête n'ont pas d'équivalents natifs
<a name="gremlin-explain-not-all-steps-converted"></a>

Neptune gère `GraphStep` et `VertexStep` en mode natif, mais si vous introduisez un élément `FoldStep` et un élément `UnfoldStep` , la sortie `explain` générée est différente :

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============
g.V().fold().unfold().out()

Original Traversal
==================
[GraphStep(vertex,[]), FoldStep, UnfoldStep, VertexStep(OUT,vertex)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
        }, annotations={path=[Vertex(?1):GraphStep], maxVarId=3}
    },
    NeptuneTraverserConverterStep
]
+ not converted into Neptune steps: [FoldStep, UnfoldStep, VertexStep(OUT,vertex)]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .], {estimatedCardinality=INFINITY}
        }, annotations={path=[Vertex(?1):GraphStep], maxVarId=3}
    },
    NeptuneTraverserConverterStep,
    NeptuneMemoryTrackerStep
]
+ not converted into Neptune steps: [FoldStep, UnfoldStep, VertexStep(OUT,vertex)]

WARNING: >> FoldStep << is not supported natively yet
```

Dans ce cas, l'élément `FoldStep` vous fait quitter l'exécution native. Même l'étape `VertexStep` suivante n'est plus gérée en mode natif, car elle apparaît en aval des étapes `Fold/Unfold`.

Pour des raisons de performances et de réduction des coûts, il est important que vous essayiez de formuler des traversées de manière à ce que le maximum de travail possible soit effectué de manière native dans le moteur de requêtes Neptune, plutôt que de procéder à des implémentations étape par étape. TinkerPop 

## Exemple de requête utilisant Neptune full-text-search
<a name="gremlin-explain-full-text-search-steps"></a>

La requête suivante utilise la recherche en texte intégral Neptune :

```
g.withSideEffect("Neptune#fts.endpoint", "some_endpoint")
  .V()
  .tail(100)
  .has("Neptune#fts mark*")
  -------
  .has("name", "Neptune#fts mark*")
  .has("Person", "name", "Neptune#fts mark*")
```

La partie `.has("name", "Neptune#fts mark*")` limite la recherche aux sommets avec `name`, alors que `.has("Person", "name", "Neptune#fts mark*")` limite la recherche aux sommets avec `name` et l'étiquette `Person`. Le résultat est la traversée suivante dans le rapport `explain` :

```
Final Traversal
[NeptuneGraphQueryStep(Vertex) {
    JoinGroupNode {
        PatternNode[(?1, termid(1,URI), ?2, termid(0,URI)) . project distinct ?1 .], {estimatedCardinality=INFINITY}
    }, annotations={path=[Vertex(?1):GraphStep], maxVarId=4}
}, NeptuneTraverserConverterStep, NeptuneTailGlobalStep(10), NeptuneTinkerpopTraverserConverterStep, NeptuneSearchStep {
    JoinGroupNode {
        SearchNode[(idVar=?3, query=mark*, field=name) . project ask .], {endpoint=some_endpoint}
    }
    JoinGroupNode {
        SearchNode[(idVar=?3, query=mark*, field=name) . project ask .], {endpoint=some_endpoint}
    }
}]
```

## Exemple d'utilisation d'`explain` lorsque le DFE est activé
<a name="gremlin-explain-dfe"></a>

Voici un exemple de rapport `explain` lorsque le moteur de requête alternatif DFE est activé :

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============

g.V().as("a").out().has("name", "josh").out().in().where(eq("a"))


Original Traversal
==================
[GraphStep(vertex,[])@[a], VertexStep(OUT,vertex), HasStep([name.eq(josh)]), VertexStep(OUT,vertex), VertexStep(IN,vertex), WherePredicateStep(eq(a))]

Converted Traversal
===================
Neptune steps:
[
    DFEStep(Vertex) {
      DFENode {
        DFEJoinGroupNode[ children={
          DFEPatternNode[(?1, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ?2, <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph>) . project DISTINCT[?1] {rangeCountEstimate=unknown}],
          DFEPatternNode[(?1, ?3, ?4, ?5) . project ALL[?1, ?4] graphFilters=(!= <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph> . ), {rangeCountEstimate=unknown}]
        }, {rangeCountEstimate=unknown}
        ]
      } [Vertex(?1):GraphStep@[a], Vertex(?4):VertexStep]
    } ,
    NeptuneTraverserConverterDFEStep
]
+ not converted into Neptune steps: HasStep([name.eq(josh)]),
Neptune steps:
[
    NeptuneInterleavingStep {
      StepInfo[joinVars=[?7, ?1], frontierElement=Vertex(?7):HasStep, pathElements={a=(last,Vertex(?1):GraphStep@[a])}, listPathElement={}, indexTime=0ms],
      DFEStep(Vertex) {
        DFENode {
          DFEJoinGroupNode[ children={
            DFEPatternNode[(?7, ?8, ?9, ?10) . project ALL[?7, ?9] graphFilters=(!= <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph> . ), {rangeCountEstimate=unknown}],
            DFEPatternNode[(?12, ?11, ?9, ?13) . project ALL[?9, ?12] graphFilters=(!= <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph> . ), {rangeCountEstimate=unknown}]
          }, {rangeCountEstimate=unknown}
          ]
        } [Vertex(?9):VertexStep, Vertex(?12):VertexStep]
      } 
    }
]
+ not converted into Neptune steps: WherePredicateStep(eq(a)),
Neptune steps:
[
    DFECleanupStep
]


Optimized Traversal
===================
Neptune steps:
[
    DFEStep(Vertex) {
      DFENode {
        DFEJoinGroupNode[ children={
          DFEPatternNode[(?1, ?3, ?4, ?5) . project ALL[?1, ?4] graphFilters=(!= defaultGraph[526] . ), {rangeCountEstimate=9223372036854775807}]
        }, {rangeCountEstimate=unknown}
        ]
      } [Vertex(?1):GraphStep@[a], Vertex(?4):VertexStep]
    } ,
    NeptuneTraverserConverterDFEStep
]
+ not converted into Neptune steps: NeptuneHasStep([name.eq(josh)]),
Neptune steps:
[
    NeptuneMemoryTrackerStep,
    NeptuneInterleavingStep {
      StepInfo[joinVars=[?7, ?1], frontierElement=Vertex(?7):HasStep, pathElements={a=(last,Vertex(?1):GraphStep@[a])}, listPathElement={}, indexTime=0ms],
      DFEStep(Vertex) {
        DFENode {
          DFEJoinGroupNode[ children={
            DFEPatternNode[(?7, ?8, ?9, ?10) . project ALL[?7, ?9] graphFilters=(!= defaultGraph[526] . ), {rangeCountEstimate=9223372036854775807}],
            DFEPatternNode[(?12, ?11, ?9, ?13) . project ALL[?9, ?12] graphFilters=(!= defaultGraph[526] . ), {rangeCountEstimate=9223372036854775807}]
          }, {rangeCountEstimate=unknown}
          ]
        } [Vertex(?9):VertexStep, Vertex(?12):VertexStep]
      } 
    }
]
+ not converted into Neptune steps: WherePredicateStep(eq(a)),
Neptune steps:
[
    DFECleanupStep
]


WARNING: >> [NeptuneHasStep([name.eq(josh)]), WherePredicateStep(eq(a))] << (or one of the children for each step) is not supported natively yet

Predicates
==========
# of predicates: 8
```

Consultez [Informations dans `explain`](#gremlin-explain-api-results) pour voir une description des sections spécifiques au DFE dans le rapport.

# API Gremlin `profile` dans Neptune
<a name="gremlin-profile-api"></a>

L'API Neptune Gremlin `profile` effectue une traversée Gremlin spécifique, collecte différentes métriques sur l'exécution et génère en sortie un rapport de profil.

Elle diffère de l'étape TinkerPop .profile () afin de pouvoir rapporter des informations spécifiques au moteur Neptune.

Le rapport de profil inclut les informations suivantes concernant le plan de requête :
+ Le pipeline de l'opérateur physique
+ Les opérations d'index pour l'exécution et la sérialisation des requêtes
+ La taille du résultat

L'API `profile` utilise une version étendue de la syntaxe d'API HTTP pour les requêtes, avec `/gremlin/profile` comme point de terminaison au lieu de `/gremlin`.

## Paramètres spécifiques à Neptune Gremlin `profile`
<a name="gremlin-profile-api-parameters"></a>
+ **profile.results** – `boolean`, valeurs autorisées : `TRUE` et `FALSE`, valeur par défaut : `TRUE`.

  Si le paramètre est défini true, les résultats de la requête sont collectés et affichés dans le rapport `profile`. Si le paramètre a pour valeur false, seul le nombre de résultats s'affiche.
+ **profile.chop** – `int`, valeur par défaut : 250.

  Si la valeur du paramètre est différente de zéro, la chaîne de résultats est tronquée à ce nombre de caractères. Cela ne empêche pas la capture de tous les résultats. Cela limite simplement la taille de la chaîne dans le rapport de profil. Si la valeur est zéro, la chaîne contient tous les résultats.
+ **profile.serializer** – `string`, valeur par défaut : `<null>`.

  Si la valeur du paramètre est différente de null, les résultats collectés sont renvoyés dans un message de réponse sérialisé au format spécifié par ce paramètre. Le nombre d'opérations d'index nécessaires pour générer ce message de réponse est signalé, ainsi que la taille en octets à envoyer au client.

  Les valeurs autorisées sont `<null>` ou n'importe laquelle des valeurs d'énumération valides du type MIME ou TinkerPop du pilote « Serializers ».

  ```
  "application/json" or "GRAPHSON"
  "application/vnd.gremlin-v1.0+json" or "GRAPHSON_V1"
  "application/vnd.gremlin-v1.0+json;types=false" or "GRAPHSON_V1_UNTYPED"
  "application/vnd.gremlin-v2.0+json" or "GRAPHSON_V2"
  "application/vnd.gremlin-v2.0+json;types=false" or "GRAPHSON_V2_UNTYPED"
  "application/vnd.gremlin-v3.0+json" or "GRAPHSON_V3"
  "application/vnd.gremlin-v3.0+json;types=false" or "GRAPHSON_V3_UNTYPED"
  "application/vnd.graphbinary-v1.0" or "GRAPHBINARY_V1"
  ```
+ **profile.indexOps** – `boolean`, valeurs autorisées : `TRUE` et `FALSE`, valeur par défaut : `FALSE`.

  Si ce paramètre a la valeur true, il affiche un rapport détaillé de toutes les opérations d'index qui ont eu lieu au cours de l'exécution et de la sérialisation des requêtes. Avertissement : ce rapport peut être très détaillé.



## Exemple de sortie de Neptune Gremlin `profile`
<a name="gremlin-profile-sample-output"></a>

Voici un exemple de requête `profile`.

```
curl -k -X POST https://your-neptune-endpoint:port/gremlin/profile \
     -d '{"gremlin":"g.V().hasLabel(\"airport\").has(\"code\", \"AUS\").emit().repeat(in().simplePath()).times(2).limit(100)", "profile.serializer":"application/vnd.gremlin-v3.0+json"}'
```

Cette requête génère le rapport `profile` suivant lorsqu'elle est exécutée sur l'exemple de graphe des lignes aériennes provenant du billet de blog, [Let Me Graph That For You - Part 1 - Air Routes](https://aws.amazon.com/blogs/database/let-me-graph-that-for-you-part-1-air-routes/).

```
*******************************************************
                Neptune Gremlin Profile
*******************************************************

Query String
==================
g.V().hasLabel("airport").has("code", "AUS").emit().repeat(in().simplePath()).times(2).limit(100)

Original Traversal
==================
[GraphStep(vertex,[]), HasStep([~label.eq(airport), code.eq(AUS)]), RepeatStep(emit(true),[VertexStep(IN,vertex), PathFilterStep(simple), RepeatEndStep],until(loops(2))), RangeGlobalStep(0,100)]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <code>, "AUS", ?) . project ?1 .], {estimatedCardinality=1, indexTime=84, hashJoin=true, joinTime=3, actualTotalOutput=1}
            PatternNode[(?1, <~label>, ?2=<airport>, <~>) . project ask .], {estimatedCardinality=3374, indexTime=29, hashJoin=true, joinTime=0, actualTotalOutput=61}
            RepeatNode {
                Repeat {
                    PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) . SimplePathFilter(?1, ?3)) .], {hashJoin=true, estimatedCardinality=50148, indexTime=0, joinTime=3}
                }
                Emit {
                    Filter(true)
                }
                LoopsCondition {
                    LoopsFilter([?1, ?3],eq(2))
                }
            }, annotations={repeatMode=BFS, emitFirst=true, untilFirst=false, leftVar=?1, rightVar=?3}
        }, finishers=[limit(100)], annotations={path=[Vertex(?1):GraphStep, Repeat[Vertex(?3):VertexStep]], joinStats=true, optimizationTime=495, maxVarId=7, executionTime=323}
    },
    NeptuneTraverserConverterStep
]

Physical Pipeline
=================
NeptuneGraphQueryStep
    |-- StartOp
    |-- JoinGroupOp
        |-- SpoolerOp(100)
        |-- DynamicJoinOp(PatternNode[(?1, <code>, "AUS", ?) . project ?1 .], {estimatedCardinality=1, indexTime=84, hashJoin=true})
        |-- SpoolerOp(100)
        |-- DynamicJoinOp(PatternNode[(?1, <~label>, ?2=<airport>, <~>) . project ask .], {estimatedCardinality=3374, indexTime=29, hashJoin=true})
        |-- RepeatOp
            |-- <upstream input> (Iteration 0) [visited=1, output=1 (until=0, emit=1), next=1]
            |-- BindingSetQueue (Iteration 1) [visited=61, output=61 (until=0, emit=61), next=61]
                |-- SpoolerOp(100)
                |-- DynamicJoinOp(PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) . SimplePathFilter(?1, ?3)) .], {hashJoin=true, estimatedCardinality=50148, indexTime=0})
            |-- BindingSetQueue (Iteration 2) [visited=38, output=38 (until=38, emit=0), next=0]
                |-- SpoolerOp(100)
                |-- DynamicJoinOp(PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) . SimplePathFilter(?1, ?3)) .], {hashJoin=true, estimatedCardinality=50148, indexTime=0})
        |-- LimitOp(100)

Runtime (ms)
============
Query Execution:  392.686
Serialization:   2636.380

Traversal Metrics
=================
Step                                                               Count  Traversers       Time (ms)    % Dur
-------------------------------------------------------------------------------------------------------------
NeptuneGraphQueryStep(Vertex)                                        100         100         314.162    82.78
NeptuneTraverserConverterStep                                        100         100          65.333    17.22
                                            >TOTAL                     -           -         379.495        -

Repeat Metrics
==============
Iteration  Visited   Output    Until     Emit     Next
------------------------------------------------------
        0        1        1        0        1        1
        1       61       61        0       61       61
        2       38       38       38        0        0
------------------------------------------------------
               100      100       38       62       62

Predicates
==========
# of predicates: 16

WARNING: reverse traversal with no edge label(s) - .in() / .both() may impact query performance

Results
=======
Count: 100
Output: [v[3], v[3600], v[3614], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12], v[47], v[49], v[136], v[13], v[15], v[16], v[17], v[18], v[389], v[20], v[21], v[22], v[23], v[24], v[25], v[26], v[27], v[28], v[416], v[29], v[30], v[430], v[31], v[9...
Response serializer: GRYO_V3D0
Response size (bytes): 23566

Index Operations
================
Query execution:
    # of statement index ops: 3
    # of unique statement index ops: 3
    Duplication ratio: 1.0
    # of terms materialized: 0
Serialization:
    # of statement index ops: 200
    # of unique statement index ops: 140
    Duplication ratio: 1.43
    # of terms materialized: 393
```

Outre les plans de requête renvoyés par un appel à Neptune `explain`, les résultats de la requête `profile` incluent des statistiques sur l'exécution des requêtes. Chaque opération de jointure est balisée avec le temps nécessaire à l'exécution de sa jointure, ainsi que le nombre réel de solutions qui lui ont été transmises.

La sortie de `profile` inclut le temps nécessaire à la phase d'exécution de la requête principale, ainsi qu'à la phase de sérialisation si l'option `profile.serializer` a été spécifiée.

La répartition des opérations d'index effectuées au cours de chaque phase est également incluse au bas de la sortie `profile`.

Notez que les exécutions consécutives d'une même requête peuvent afficher des résultats différents en termes d'opérations d'exécution et d'index en raison de la mise en cache.

Pour les requêtes utilisant l'étape `repeat()`, une répartition de la frontière sur chaque itération est disponible si l'étape `repeat()` a été réduite et intégrée dans une étape `NeptuneGraphQueryStep`.

## Différences entre les rapports `profile` lorsque le DFE est activé
<a name="gremlin-profile-dfe-output"></a>

Lorsque le moteur de requête alternatif DFE Neptune est activé, la sortie `profile` est quelque peu différente :

**Traversée optimisée :** cette section est similaire à celle de la sortie `explain`, mais contient des informations supplémentaires. Cela inclut le type d'opérateurs DFE pris en compte lors de la planification, ainsi que les estimations de coûts associées au pire et au meilleur scénario.

**Pipeline physique :** cette section capture les opérateurs utilisés pour exécuter la requête. Les éléments `DFESubQuery` procèdent à l'abstraction du plan physique utilisé par le DFE pour exécuter la partie du plan dont il est responsable. Les éléments `DFESubQuery` sont présentés dans la section suivante où les statistiques DFE sont répertoriées.

**DFEQueryStatistiques du moteur :** cette section s'affiche uniquement lorsqu'au moins une partie de la requête est exécutée par DFE. Elle décrit diverses statistiques d'exécution spécifiques au DFE et contient une répartition détaillée du temps passé dans les différentes parties de l'exécution de la requête, par `DFESubQuery`.

Les sous-requêtes imbriquées dans différents éléments `DFESubQuery` ne sont pas hiérarchisées dans cette section, et les identifiants uniques sont marqués d'un en-tête commençant par `subQuery=`.

**Métriques de traversée :** cette section présente les métriques de traversée au niveau des étapes et, lorsque le moteur DFE exécute la totalité ou une partie de la requête, affiche les métriques pour `DFEStep` et/ou `NeptuneInterleavingStep`. Consultez [Réglage des requêtes Gremlin à l'aide d'`explain` et de `profile`](gremlin-traversal-tuning.md).

**Note**  
Le DFE est une fonctionnalité expérimentale publiée en mode laboratoire, de sorte que le format exact de la sortie `profile` est toujours sujet à modification.

## Exemple de sortie `profile` lorsque le moteur Neptune Dataflow (DFE) est activé
<a name="gremlin-profile-sample-dfe-output"></a>

Lorsque le moteur DFE est utilisé pour exécuter des requêtes Gremlin, la sortie de l'[API Gremlin `profile`](#gremlin-profile-api) est mise en forme comme indiqué dans l'exemple ci-dessous.

Interrogation :

```
curl https://your-neptune-endpoint:port/gremlin/profile \
  -d "{\"gremlin\": \"g.withSideEffect('Neptune#useDFE', true).V().has('code', 'ATL').out()\"}"
```

```
*******************************************************
                    Neptune Gremlin Profile
    *******************************************************

    Query String
    ==================
    g.withSideEffect('Neptune#useDFE', true).V().has('code', 'ATL').out()

    Original Traversal
    ==================
    [GraphStep(vertex,[]), HasStep([code.eq(ATL)]), VertexStep(OUT,vertex)]

    Optimized Traversal
    ===================
    Neptune steps:
    [
        DFEStep(Vertex) {
          DFENode {
            DFEJoinGroupNode[null](
              children=[
                DFEPatternNode((?1, vp://code[419430926], ?4, defaultGraph[526]) . project DISTINCT[?1] objectFilters=(in(ATL[452987149]) . ), {rangeCountEstimate=1},
                  opInfo=(type=PipelineJoin, cost=(exp=(in=1.00,out=1.00,io=0.00,comp=0.00,mem=0.00),wc=(in=1.00,out=1.00,io=0.00,comp=0.00,mem=0.00)),
                    disc=(type=PipelineScan, cost=(exp=(in=1.00,out=1.00,io=0.00,comp=0.00,mem=34.00),wc=(in=1.00,out=1.00,io=0.00,comp=0.00,mem=34.00))))),
                DFEPatternNode((?1, ?5, ?6, ?7) . project ALL[?1, ?6] graphFilters=(!= defaultGraph[526] . ), {rangeCountEstimate=9223372036854775807})],
              opInfo=[
                OperatorInfoWithAlternative[
                  rec=(type=PipelineJoin, cost=(exp=(in=1.00,out=27.76,io=0.00,comp=0.00,mem=0.00),wc=(in=1.00,out=27.76,io=0.00,comp=0.00,mem=0.00)),
                    disc=(type=PipelineScan, cost=(exp=(in=1.00,out=27.76,io=Infinity,comp=0.00,mem=295147905179352830000.00),wc=(in=1.00,out=27.76,io=Infinity,comp=0.00,mem=295147905179352830000.00)))),
                  alt=(type=PipelineScan, cost=(exp=(in=1.00,out=27.76,io=Infinity,comp=0.00,mem=295147905179352830000.00),wc=(in=1.00,out=27.76,io=Infinity,comp=0.00,mem=295147905179352830000.00)))]])
          } [Vertex(?1):GraphStep, Vertex(?6):VertexStep]
        } ,
        NeptuneTraverserConverterDFEStep,
        DFECleanupStep
    ]


    Physical Pipeline
    =================
    DFEStep
        |-- DFESubQuery1

    DFEQueryEngine Statistics
    =================
    DFESubQuery1
    ╔════╤════════╤════════╤═══════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤════════╤═══════════╗
    ║ ID │ Out #1 │ Out #2 │ Name                  │ Arguments                                                                                                    │ Mode │ Units In │ Units Out │ Ratio  │ Time (ms) ║
    ╠════╪════════╪════════╪═══════════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪════════╪═══════════╣
    ║ 0  │ 1      │ -      │ DFESolutionInjection  │ solutions=[]                                                                                                 │ -    │ 0        │ 1         │ 0.00   │ 0.01      ║
    ║    │        │        │                       │ outSchema=[]                                                                                                 │      │          │           │        │           ║
    ╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 1  │ 2      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#089f43e3-4d71-4259-8d19-254ff63cee04/graph_1 │ -    │ 1        │ 1         │ 1.00   │ 0.02      ║
    ╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 2  │ 3      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#089f43e3-4d71-4259-8d19-254ff63cee04/graph_2 │ -    │ 1        │ 242       │ 242.00 │ 0.02      ║
    ╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 3  │ 4      │ -      │ DFEMergeChunks        │ -                                                                                                            │ -    │ 242      │ 242       │ 1.00   │ 0.01      ║
    ╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 4  │ -      │ -      │ DFEDrain              │ -                                                                                                            │ -    │ 242      │ 0         │ 0.00   │ 0.01      ║
    ╚════╧════════╧════════╧═══════════════════════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧════════╧═══════════╝


    subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#089f43e3-4d71-4259-8d19-254ff63cee04/graph_1
    ╔════╤════════╤════════╤══════════════════════╤═════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
    ║ ID │ Out #1 │ Out #2 │ Name                 │ Arguments                                                   │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
    ╠════╪════════╪════════╪══════════════════════╪═════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
    ║ 0  │ 1      │ -      │ DFEPipelineScan      │ pattern=Node(?1) with property 'code' as ?4 and label 'ALL' │ -    │ 0        │ 1         │ 0.00  │ 0.22      ║
    ║    │        │        │                      │ inlineFilters=[(?4 IN ["ATL"])]                             │      │          │           │       │           ║
    ║    │        │        │                      │ patternEstimate=1                                           │      │          │           │       │           ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
    ║ 1  │ 2      │ -      │ DFEMergeChunks       │ -                                                           │ -    │ 1        │ 1         │ 1.00  │ 0.02      ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
    ║ 2  │ 4      │ -      │ DFERelationalJoin    │ joinVars=[]                                                 │ -    │ 2        │ 1         │ 0.50  │ 0.09      ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
    ║ 3  │ 2      │ -      │ DFESolutionInjection │ solutions=[]                                                │ -    │ 0        │ 1         │ 0.00  │ 0.01      ║
    ║    │        │        │                      │ outSchema=[]                                                │      │          │           │       │           ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
    ║ 4  │ -      │ -      │ DFEDrain             │ -                                                           │ -    │ 1        │ 0         │ 0.00  │ 0.01      ║
    ╚════╧════════╧════════╧══════════════════════╧═════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝


    subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#089f43e3-4d71-4259-8d19-254ff63cee04/graph_2
    ╔════╤════════╤════════╤══════════════════════╤═════════════════════════════════════╤══════╤══════════╤═══════════╤════════╤═══════════╗
    ║ ID │ Out #1 │ Out #2 │ Name                 │ Arguments                           │ Mode │ Units In │ Units Out │ Ratio  │ Time (ms) ║
    ╠════╪════════╪════════╪══════════════════════╪═════════════════════════════════════╪══════╪══════════╪═══════════╪════════╪═══════════╣
    ║ 0  │ 1      │ -      │ DFESolutionInjection │ solutions=[]                        │ -    │ 0        │ 1         │ 0.00   │ 0.01      ║
    ║    │        │        │                      │ outSchema=[?1]                      │      │          │           │        │           ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 1  │ 2      │ 3      │ DFETee               │ -                                   │ -    │ 1        │ 2         │ 2.00   │ 0.01      ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 2  │ 4      │ -      │ DFEDistinctColumn    │ column=?1                           │ -    │ 1        │ 1         │ 1.00   │ 0.21      ║
    ║    │        │        │                      │ ordered=false                       │      │          │           │        │           ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 3  │ 5      │ -      │ DFEHashIndexBuild    │ vars=[?1]                           │ -    │ 1        │ 1         │ 1.00   │ 0.03      ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 4  │ 5      │ -      │ DFEPipelineJoin      │ pattern=Edge((?1)-[?7:?5]->(?6))    │ -    │ 1        │ 242       │ 242.00 │ 0.51      ║
    ║    │        │        │                      │ constraints=[]                      │      │          │           │        │           ║
    ║    │        │        │                      │ patternEstimate=9223372036854775807 │      │          │           │        │           ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 5  │ 6      │ 7      │ DFESync              │ -                                   │ -    │ 243      │ 243       │ 1.00   │ 0.02      ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 6  │ 8      │ -      │ DFEForwardValue      │ -                                   │ -    │ 1        │ 1         │ 1.00   │ 0.01      ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 7  │ 8      │ -      │ DFEForwardValue      │ -                                   │ -    │ 242      │ 242       │ 1.00   │ 0.02      ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 8  │ 9      │ -      │ DFEHashIndexJoin     │ -                                   │ -    │ 243      │ 242       │ 1.00   │ 0.31      ║
    ╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼────────┼───────────╢
    ║ 9  │ -      │ -      │ DFEDrain             │ -                                   │ -    │ 242      │ 0         │ 0.00   │ 0.01      ║
    ╚════╧════════╧════════╧══════════════════════╧═════════════════════════════════════╧══════╧══════════╧═══════════╧════════╧═══════════╝


    Runtime (ms)
    ============
    Query Execution: 11.744

    Traversal Metrics
    =================
    Step                                                               Count  Traversers       Time (ms)    % Dur
    -------------------------------------------------------------------------------------------------------------
    DFEStep(Vertex)                                                      242         242          10.849    95.48
    NeptuneTraverserConverterDFEStep                                     242         242           0.514     4.52
                                                >TOTAL                     -           -          11.363        -

    Predicates
    ==========
    # of predicates: 18

    Results
    =======
    Count: 242


    Index Operations
    ================
    Query execution:
        # of statement index ops: 0
        # of terms materialized: 0
```

**Note**  
Le moteur DFE étant une fonctionnalité expérimentale publiée en mode laboratoire, le format exact de la sortie `profile` peut changer.

# Réglage des requêtes Gremlin à l'aide d'`explain` et de `profile`
<a name="gremlin-traversal-tuning"></a>

[Vous pouvez souvent ajuster vos requêtes Gremlin dans Amazon Neptune pour obtenir de meilleures performances, en utilisant les informations mises à votre disposition dans les rapports fournis par le biais de l'explication et du profil de [Neptune](gremlin-explain-api.md).](gremlin-profile-api.md) APIs Pour ce faire, il est utile de comprendre comment Neptune traite les traversées Gremlin.

**Important**  
Une modification a été apportée à TinkerPop la version 3.4.11 qui améliore l'exactitude du traitement des requêtes, mais qui, pour le moment, peut parfois avoir un impact sérieux sur les performances des requêtes.  
Par exemple, une requête de ce type peut être beaucoup plus lente :  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  out()
```
Les sommets après le pas de limite sont désormais récupérés de manière non optimale en raison de la modification 3.4.11. TinkerPop Pour éviter cela, vous pouvez modifier la requête en ajoutant l'étape barrier() à tout moment après `order().by()`. Par exemple :  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  barrier().
  out()
```
TinkerPop [La version 3.4.11 a été activée dans la version 1.0.5.0 du moteur Neptune.](engine-releases-1.0.5.0.md)

## Comprendre le traitement des traversées Gremlin dans Neptune
<a name="gremlin-traversal-processing"></a>

Lorsqu'une traversée Gremlin est envoyée à Neptune, trois processus principaux la convertissent en un plan d'exécution sous-jacent à exécuter par le moteur. Il s'agit de l'analyse, de la conversion et de l'optimisation :

![\[Trois processus convertissent une requête Gremlin en plan d'exécution.\]](http://docs.aws.amazon.com/fr_fr/neptune/latest/userguide/images/Gremlin_traversal_processing.png)


### Processus d'analyse des traversées
<a name="gremlin-traversal-processing-parsing"></a>

La première étape du traitement d'une traversée consiste à l'analyser dans un langage commun. [Dans Neptune, ce langage commun est l'ensemble des TinkerPop étapes qui font partie de l'TinkerPopAPI.](http://tinkerpop.apache.org/javadocs/3.4.8/full/org/apache/tinkerpop/gremlin/process/traversal/Step.html) Chacune de ces étapes représente une unité de calcul au sein de la traversée.

Vous pouvez envoyer une traversée Gremlin à Neptune sous forme de chaîne ou de bytecode. Le point de terminaison REST et la méthode `submit()` du pilote client Java envoient des traversées sous forme de chaînes, comme dans cet exemple :

```
client.submit("g.V()")
```

Les applications et les pilotes de langage utilisant les [variantes du langage Gremlin (GLV)](https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/) envoient les traversées sous forme de bytecode.

### Processus de conversion des traversées
<a name="gremlin-traversal-processing-conversion"></a>

La deuxième étape du traitement d'une traversée consiste à convertir ses TinkerPop étapes en un ensemble d'étapes Neptune converties et non converties. La plupart des étapes du langage de requête TinkerPop Apache Gkremlin sont converties en étapes spécifiques à Neptune optimisées pour s'exécuter sur le moteur Neptune sous-jacent. Lorsqu'une TinkerPop étape sans équivalent Neptune est rencontrée dans une traversée, cette étape et toutes les étapes suivantes de la traversée sont traitées par le moteur de requête. TinkerPop 

Pour plus d'informations sur les étapes qui peuvent être converties et dans quelles circonstances, consultez [Prise en charge des étapes Gremlin](gremlin-step-support.md).

### Processus d'optimisation des traversées
<a name="gremlin-traversal-processing-optimization"></a>

La dernière étape du traitement des traversées consiste à exécuter la série d'étapes converties et non converties via l'optimiseur, afin de déterminer le meilleur plan d'exécution. Le résultat de cette optimisation est le plan d'exécution traité par le moteur Neptune.

## Utilisation de l'API Neptune Gremlin `explain` pour ajuster les requêtes
<a name="gremlin-traversal-tuning-explain"></a>

L'API Neptune explain n'est pas identique à l'étape Gremlin `explain()`. Elle renvoie le plan d'exécution final que le moteur Neptune peut traiter lors de l'exécution de la requête. Comme elle n'effectue aucun traitement, elle renvoie le même plan quels que soient les paramètres utilisés, et sa sortie ne contient aucune statistique sur l'exécution réelle.

Prenons l'exemple de la traversée simple suivante qui permet de trouver tous les sommets de l'aéroport pour Anchorage :

```
g.V().has('code','ANC')
```

Il existe deux façons d'exécuter cette traversée via l'API Neptune `explain`. La première méthode consiste à effectuer un appel REST au point de terminaison explain, comme suit :

```
curl -X POST https://your-neptune-endpoint:port/gremlin/explain -d '{"gremlin":"g.V().has('code','ANC')"}'
```

La deuxième méthode consiste à utiliser la magie cellulaire [%%gremlin](notebooks-magics.md#notebooks-cell-magics-gremlin) du workbench Neptune avec le paramètre `explain`. Cela transmet le parcours contenu dans le corps de la cellule à l'API Neptune `explain`, puis affiche le résultat obtenu lorsque vous exécutez la cellule :

```
%%gremlin explain

g.V().has('code','ANC')
```

La sortie d'API `explain` qui en résulte décrit le plan d'exécution de Neptune pour la traversée. Comme vous pouvez le voir sur l'image ci-dessous, le plan inclut chacune des trois étapes du pipeline de traitement :

![\[Sortie d'API explain pour une traversée Gremlin simple.\]](http://docs.aws.amazon.com/fr_fr/neptune/latest/userguide/images/Gremlin_explain_output_1.png)


### Réglage d'une traversée en examinant les étapes qui ne sont pas converties
<a name="gremlin-traversal-tuning-explain-non-converted-steps"></a>

L'une des premières choses à rechercher dans la sortie de l'API Neptune `explain` concerne les étapes Gremlin qui ne sont pas converties en étapes natives Neptune. Dans un plan de requête, lorsqu'une étape ne peut pas être convertie en étape native Neptune, elle est traitée par le serveur Gremlin, ainsi que toutes les étapes suivantes du plan.

Dans l'exemple ci-dessus, toutes les étapes de la traversée ont été converties. Examinons la sortie d'API `explain` pour cette traversée :

```
g.V().has('code','ANC').out().choose(hasLabel('airport'), values('code'), constant('Not an airport'))
```

Comme vous pouvez le voir sur l'image ci-dessous, Neptune n'a pas pu convertir l'étape `choose()` :

![\[Sortie d'API explain dans laquelle les étapes ne peuvent pas toutes être converties.\]](http://docs.aws.amazon.com/fr_fr/neptune/latest/userguide/images/Gremlin_explain_output_2.png)


Il existe plusieurs façons d'ajuster les performances de la traversée. La première consiste à la réécrire de manière à éliminer l'étape qui n'a pas pu être convertie. Une autre solution consiste à déplacer l'étape vers la fin de la traversée afin que toutes les autres étapes puissent être converties en étapes natives.

Un plan de requête dont les étapes ne sont pas converties n'a pas toujours besoin d'être ajusté. Si les étapes qui ne peuvent pas être converties se situent à la fin de la traversée et sont liées à la mise en forme de la sortie plutôt qu'à la manière dont le graphe est parcouru, elles peuvent avoir peu d'effet sur les performances.

### 
<a name="gremlin-traversal-tuning-explain-unindexed-lookups"></a>

Lorsque vous examinez la sortie de l'API Neptune `explain`, tenez aussi compte des étapes qui n'utilisent pas d'index. La traversée suivante permet de trouver tous les aéroports dont les vols atterrissent à Anchorage :

```
g.V().has('code','ANC').in().values('code')
```

La sortie de l'API explain pour cette traversée est la suivante :

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============

g.V().has('code','ANC').in().values('code')

Original Traversal
==================
[GraphStep(vertex,[]), HasStep([code.eq(ANC)]), VertexStep(IN,vertex), PropertiesStep([code],value)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(PropertyValue) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
            PatternNode[(?1, <code>, "ANC", ?) . project ask .]
            PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .]
            PatternNode[(?3, <~label>, ?4, <~>) . project ask .]
            PatternNode[(?3, ?7, ?8, <~>) . project ?3,?8 . ContainsFilter(?7 in (<code>)) .]
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9}
    },
    NeptuneTraverserConverterStep
]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(PropertyValue) {
        JoinGroupNode {
            PatternNode[(?1, <code>, "ANC", ?) . project ?1 .], {estimatedCardinality=1}
            PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=INFINITY}
            PatternNode[(?3, ?7=<code>, ?8, <~>) . project ?3,?8 .], {estimatedCardinality=7564}
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9}
    },
    NeptuneTraverserConverterStep
]

Predicates
==========
# of predicates: 26

WARNING: reverse traversal with no edge label(s) - .in() / .both() may impact query performance
```

Le message `WARNING` au bas de la sortie apparaît parce que l'étape `in()` de la traversée ne peut pas être gérée à l'aide de l'un des trois index gérés par Neptune (voir [Comment les instructions sont indexées dans Neptune](feature-overview-storage-indexing.md) et [Déclarations Gremlin dans Neptune](gremlin-explain-background-statements.md)). Comme l'étape `in()` ne contient aucun filtre d'arête, elle ne peut pas être résolue à l'aide de l'index `SPOG`, `POGS` ou `GPSO`. À la place, Neptune doit effectuer une analyse d'union pour trouver les sommets demandés, ce qui est beaucoup moins efficace.

Dans cette situation, vous pouvez ajuster la traversée de deux façons. La première consiste à ajouter un ou plusieurs critères de filtrage à l'étape `in()` afin qu'une recherche indexée puisse être utilisée pour résoudre la requête. Concernant l'exemple ci-dessus, cela peut être :

```
g.V().has('code','ANC').in('route').values('code')
```

La sortie de l'API Neptune `explain` pour la traversée révisée ne contient plus le message `WARNING` :

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============

g.V().has('code','ANC').in('route').values('code')

Original Traversal
==================
[GraphStep(vertex,[]), HasStep([code.eq(ANC)]), VertexStep(IN,[route],vertex), PropertiesStep([code],value)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(PropertyValue) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
            PatternNode[(?1, <code>, "ANC", ?) . project ask .]
            PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) . ContainsFilter(?5 in (<route>)) .]
            PatternNode[(?3, <~label>, ?4, <~>) . project ask .]
            PatternNode[(?3, ?7, ?8, <~>) . project ?3,?8 . ContainsFilter(?7 in (<code>)) .]
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9}
    },
    NeptuneTraverserConverterStep
]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(PropertyValue) {
        JoinGroupNode {
            PatternNode[(?1, <code>, "ANC", ?) . project ?1 .], {estimatedCardinality=1}
            PatternNode[(?3, ?5=<route>, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=32042}
            PatternNode[(?3, ?7=<code>, ?8, <~>) . project ?3,?8 .], {estimatedCardinality=7564}
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9}
    },
    NeptuneTraverserConverterStep
]

Predicates
==========
# of predicates: 26
```

Si vous exécutez de nombreuses traversées de ce type, vous pouvez également les exécuter dans un cluster de bases de données Neptune dont l'index `OSGP` facultatif est activé (voir [Activation d'un index OSGP](feature-overview-storage-indexing.md#feature-overview-storage-indexing-osgp)). L'activation d'un index `OSGP` présente des inconvénients :
+ Elle doit être activée dans un cluster de bases de données avant tout chargement de données.
+ Les taux d'insertion des sommets et des arêtes peuvent ralentir de jusqu'à 23 %.
+ L'utilisation du stockage augmente d'environ 20 %.
+ Les requêtes de lecture qui répartissent les demandes sur tous les index peuvent accroître les temps de latence.

L'utilisation d'un index `OSGP` est tout à fait justifiée pour un ensemble restreint de modèles de requêtes, mais à moins que vous ne les exécutiez fréquemment, il est généralement préférable de faire en sorte que les traversées que vous écrivez puissent être résolues à l'aide des trois index principaux.

### Utilisation d'un grand nombre de prédicats
<a name="gremlin-traversal-tuning-explain-many-predicates"></a>

Neptune traite chaque étiquette d'arête et chaque nom de propriété de sommet ou d'arête distinct dans le graphe comme un prédicat. Il est conçu par défaut pour fonctionner avec un nombre relativement faible de prédicats distincts. Lorsque les données du graphe contiennent plus de quelques milliers de prédicats, les performances peuvent se dégrader.

La sortie Neptune `explain` vous en avertit si c'est le cas :

```
Predicates
==========
# of predicates: 9549
WARNING: high predicate count (# of distinct property names and edge labels)
```

S'il n'est pas pratique de retravailler votre modèle de données pour réduire le nombre d'étiquettes et de propriétés, et donc le nombre de prédicats, le meilleur moyen d'ajuster les traversées consiste à les exécuter dans un cluster de bases de données dont l'index `OSGP` est activé, comme indiqué ci-dessus.

## Utilisation de l'API Neptune Gremlin `profile` pour ajuster les traversées
<a name="gremlin-traversal-tuning-profile"></a>

L'API Neptune `profile` est très différente de l'étape Gremlin `profile()`. Comme l'API `explain`, sa sortie inclut le plan de requête que le moteur Neptune utilisera lors de l'exécution de la traversée. En outre, la sortie `profile` inclut les statistiques d'exécution réelles de la traversée, compte tenu de la façon dont ses paramètres sont définis.

Là aussi, prenons l'exemple de la traversée simple qui permet de trouver tous les sommets de l'aéroport pour Anchorage :

```
g.V().has('code','ANC')
```

Comme avec l'API `explain`, vous pouvez invoquer l'API `profile` à l'aide d'un appel REST :

```
curl -X POST https://your-neptune-endpoint:port/gremlin/profile -d '{"gremlin":"g.V().has('code','ANC')"}'
```

Utilisez également la magie cellulaire [%%gremlin](notebooks-magics.md#notebooks-cell-magics-gremlin) du workbench Neptune avec le paramètre `profile`. Cela transmet le parcours contenu dans le corps de la cellule à l'API Neptune `profile`, puis affiche le résultat obtenu lorsque vous exécutez la cellule :

```
%%gremlin profile

g.V().has('code','ANC')
```

La sortie d'API `profile` qui en résulte contient à la fois le plan d'exécution de Neptune pour la traversée et les statistiques relatives à l'exécution du plan, comme vous pouvez le voir sur cette image :

![\[Exemple de sortie de l'API Neptune profile.\]](http://docs.aws.amazon.com/fr_fr/neptune/latest/userguide/images/Gremlin_profile_output_1.png)


Dans la sortie `profile`, la section du plan d'exécution contient uniquement le plan d'exécution final de la traversée, et non les étapes intermédiaires. La section du pipeline contient les opérations physiques du pipeline qui ont été effectuées ainsi que le temps réel (en millisecondes) nécessaire à l'exécution de la traversée. La métrique d'exécution est extrêmement utile pour comparer le temps nécessaire à deux versions différentes d'une traversée lorsque vous les optimisez.

**Note**  
La durée d'exécution initiale d'une traversée est généralement plus longue que celle des exécutions suivantes, car la première entraîne la mise en cache des données pertinentes.

La troisième section de la sortie `profile` contient les statistiques d'exécution et les résultats de la traversée. Pour voir comment ces informations peuvent être utiles pour ajuster une traversée, prenons l'exemple de la traversée suivante, qui permet de trouver tous les aéroports dont le nom commence par « Anchora » et tous les aéroports accessibles en deux étapes à partir de ces aéroports, en renvoyant le code des aéroports, les itinéraires de vol et les distances :

```
%%gremlin profile

g.withSideEffect("Neptune#fts.endpoint", "{your-OpenSearch-endpoint-URL").
    V().has("city", "Neptune#fts Anchora~").
    repeat(outE('route').inV().simplePath()).times(2).
    project('Destination', 'Route').
        by('code').
        by(path().by('code').by('dist'))
```

### Métriques de traversée dans la sortie de l'API Neptune `profile`
<a name="gremlin-traversal-tuning-profile-traversal-metrics"></a>

Le premier ensemble de métriques disponible dans toutes les sorties `profile` est celui des métriques de traversée. Elles sont similaires aux métriques de l'étape Gremlin `profile()`, à quelques différences près :

```
Traversal Metrics
=================
Step                                                               Count  Traversers       Time (ms)    % Dur
-------------------------------------------------------------------------------------------------------------
NeptuneGraphQueryStep(Vertex)                                       3856        3856          91.701     9.09
NeptuneTraverserConverterStep                                       3856        3856          38.787     3.84
ProjectStep([Destination, Route],[value(code), ...                  3856        3856         878.786    87.07
  PathStep([value(code), value(dist)])                              3856        3856         601.359
                                            >TOTAL                     -           -        1009.274        -
```

La première colonne du tableau des métriques de traversée répertorie les étapes exécutées par la traversée. Les deux premières étapes sont généralement les étapes spécifiques à Neptune, `NeptuneGraphQueryStep` et `NeptuneTraverserConverterStep`.

`NeptuneGraphQueryStep` représente le temps d'exécution pour toute la partie de la traversée qui pourrait être convertie et exécutée nativement par le moteur Neptune.

`NeptuneTraverserConverterStep`représente le processus de conversion de la sortie de ces étapes converties en TinkerPop traverseurs qui permettent de traiter les étapes qui n'ont pas pu être converties, le cas échéant, ou de renvoyer les résultats dans un format TinkerPop compatible.

Dans l'exemple ci-dessus, nous avons plusieurs étapes non converties. Nous voyons donc que chacune de ces TinkerPop étapes (`ProjectStep`,`PathStep`) apparaît alors sous forme de ligne dans le tableau.

La deuxième colonne du tableau indique le nombre de traversers *représentés* qui sont passés par l'étape, tandis que la troisième colonne indique le nombre de traverseurs qui sont passés par cette étape, comme expliqué dans la documentation de l'[étape du TinkerPop profil](https://tinkerpop.apache.org/docs/current/reference/#profile-step). `Count` `Traversers`

Dans notre exemple, 3 856 sommets et 3 856 traverseurs sont renvoyés par `NeptuneGraphQueryStep`, et ces nombres restent les mêmes pendant le reste du traitement car `ProjectStep` et `PathStep` mettent en forme les résultats, sans les filtrer.

**Note**  
Contrairement à cela TinkerPop, le moteur Neptune n'optimise pas les performances en augmentant le nombre de ses *étapes et de* ses `NeptuneGraphQueryStep` étapes. `NeptuneTraverserConverterStep` Le groupage est l' TinkerPopopération qui combine des traverseurs situés sur le même sommet afin de réduire la surcharge opérationnelle, et c'est ce qui explique la différence entre les `Traversers` nombres `Count` et. Comme le groupage ne se produit que par étapes déléguées TinkerPop par Neptune, et non par étapes gérées nativement par Neptune, `Count` les colonnes et diffèrent rarement. `Traverser`

La colonne Temps indique le nombre de millisecondes que l'étape a duré, tandis que la colonne `% Dur` indique le pourcentage du temps de traitement total que l'étape a pris. Ces métriques vous indiquent sur quoi concentrer vos efforts de réglage en présentant les étapes qui ont pris le plus de temps.

### Métriques d'opérations d'index dans la sortie de l'API Neptune `profile`
<a name="gremlin-traversal-tuning-profile-index-operations"></a>

Les opérations d'indexation constituent un autre ensemble de métriques figurant dans les résultats de l'API de profil Neptune :

```
Index Operations
================
Query execution:
    # of statement index ops: 23191
    # of unique statement index ops: 5960
    Duplication ratio: 3.89
    # of terms materialized: 0
```

Ces métriques fournissent les informatons suivantes :
+ Nombre total de recherches d'index.
+ Nombre de recherches d'index uniques effectuées.
+ Ratio entre le nombre total de recherches d'index et le nombre total de recherches uniques. Un ratio inférieur indique une redondance moindre.
+ Nombre de termes matérialisés à partir du dictionnaire.

### Métriques de répétitions dans la sortie de l'API Neptune `profile`
<a name="gremlin-traversal-tuning-profile-repeat-metrics"></a>

Si votre traversée utilise une étape `repeat()` comme dans l'exemple ci-dessus, une section contenant des métriques de répétition apparaît dans la sortie `profile` :

```
Repeat Metrics
==============
Iteration  Visited   Output    Until     Emit     Next
------------------------------------------------------
        0        2        0        0        0        2
        1       53        0        0        0       53
        2     3856     3856     3856        0        0
------------------------------------------------------
              3911     3856     3856        0       55
```

Ces métriques fournissent les informatons suivantes :
+ Nombre de boucles pour une ligne (colonne `Iteration`)
+ Nombre d'éléments auxquels la boucle a accédé (colonne `Visited`)
+ Nombre d'éléments générés par la boucle (colonne `Output`)
+ Dernier élément généré par la boucle (colonne `Until`)
+ Nombre d'éléments émis par la boucle (colonne `Emit`)
+ Nombre d'éléments étant passés de la boucle à la boucle suivante (colonne `Next`)

Ces métriques de répétition sont très utiles pour comprendre le facteur de ramification de la traversée. Elles vous permettent de vous faire une idée de la quantité de travail effectuée par la base de données. Vous pouvez utiliser ces chiffres pour diagnostiquer les problèmes de performances, en particulier lorsqu'une même traversée fonctionne de manière radicalement différente selon les paramètres.

### Métriques de recherche en texte intégral dans la sortie de l'API Neptune `profile`
<a name="gremlin-traversal-tuning-profile-fts-metrics"></a>

Lorsqu'une traversée utilise une [recherche en texte intégral](full-text-search.md), comme dans l'exemple ci-dessus, une section contenant les métriques de recherche en texte intégral (FTS) apparaît dans la sortie `profile` :

```
FTS Metrics
==============
SearchNode[(idVar=?1, query=Anchora~, field=city) . project ?1 .],
    {endpoint=your-OpenSearch-endpoint-URL, incomingSolutionsThreshold=1000, estimatedCardinality=INFINITY,
    remoteCallTimeSummary=[total=65, avg=32.500000, max=37, min=28],
    remoteCallTime=65, remoteCalls=2, joinTime=0, indexTime=0, remoteResults=2}

    2 result(s) produced from SearchNode above
```

Cela montre la requête envoyée au cluster ElasticSearch (ES) et indique plusieurs mesures relatives à l'interaction avec ElasticSearch lesquelles vous pouvez identifier les problèmes de performances liés à la recherche en texte intégral :
+ Informations récapitulatives sur les appels dans l' ElasticSearch index :
  + Nombre total de millisecondes requis par tous les appels à distance pour satisfaire la requête (`total`).
  + Nombre moyen de millisecondes passées dans un appel à distance (`avg`).
  + Nombre minimum de millisecondes passées dans un appel à distance (`min`).
  + Nombre maximum de millisecondes passées dans un appel à distance (`max`).
+ Durée totale consommée par RemoteCalls to ElasticSearch ()`remoteCallTime`.
+ Le nombre d'appels à distance effectués vers ElasticSearch ()`remoteCalls`.
+ Le nombre de millisecondes passées à joindre les ElasticSearch résultats (). `joinTime`
+ Nombre de millisecondes passées dans les recherches d'index (`indexTime`).
+ Le nombre total de résultats renvoyés par ElasticSearch (`remoteResults`).

# Prise en charge des étapes Gremlin natives dans Amazon Neptune
<a name="gremlin-step-support"></a>

Le moteur Amazon Neptune n'offre actuellement pas de prise en charge native complète pour toutes les étapes Gremlin, comme expliqué dans [Réglage des requêtes Gremlin](gremlin-traversal-tuning.md). La prise en charge actuelle se divise en quatre catégories :
+ [Étapes Gremlin qui peuvent toujours être converties en opérations natives du moteur Neptune](#gremlin-steps-always)
+ [Étapes Gremlin qui peuvent être converties en opérations natives du moteur Neptune dans certains cas](#gremlin-steps-sometimes) 
+ [Étapes Gremlin qui sont jamais converties en opérations natives du moteur Neptune](#gremlin-steps-never) 
+ [Étapes Gremlin qui ne sont pas du tout prises en charge dans Neptune](#neptune-gremlin-steps-unsupported) 

## Étapes Gremlin qui peuvent toujours être converties en opérations natives du moteur Neptune
<a name="gremlin-steps-always"></a>

De nombreuses étapes Gremlin peuvent être converties en opérations natives du moteur Neptune tant qu'elles répondent aux conditions suivantes :
+ Elles ne sont pas précédées dans la requête d'une étape qui ne peut pas être convertie.
+ Leur étape parent, le cas échéant, peut être convertie.
+ Toutes leurs traversées enfants, le cas échéant, peuvent être converties.

Les étapes Gremlin suivantes sont toujours converties en opérations natives du moteur Neptune si elles répondent à ces conditions :
+ [and( )](http://tinkerpop.apache.org/docs/current/reference/#and-step)
+ [as( )](http://tinkerpop.apache.org/docs/current/reference/#as-step)
+ [count( )](http://tinkerpop.apache.org/docs/current/reference/#count-step)
+ [E( )](http://tinkerpop.apache.org/docs/current/reference/#graph-step)
+ [emit( )](http://tinkerpop.apache.org/docs/current/reference/#emit-step)
+ [explain( )](http://tinkerpop.apache.org/docs/current/reference/#explain-step)
+ [group( )](http://tinkerpop.apache.org/docs/current/reference/#group-step)
+ [groupCount( )](http://tinkerpop.apache.org/docs/current/reference/#groupcount-step)
+ [identity( )](http://tinkerpop.apache.org/docs/current/reference/#identity-step)
+ [is( )](http://tinkerpop.apache.org/docs/current/reference/#is-step)
+ [key( )](http://tinkerpop.apache.org/docs/current/reference/#key-step)
+ [label( )](http://tinkerpop.apache.org/docs/current/reference/#label-step)
+ [limit( )](http://tinkerpop.apache.org/docs/current/reference/#limit-step)
+ [local( )](http://tinkerpop.apache.org/docs/current/reference/#local-step)
+ [loops( )](http://tinkerpop.apache.org/docs/current/reference/#loops-step)
+ [not( )](http://tinkerpop.apache.org/docs/current/reference/#not-step)
+ [or( )](http://tinkerpop.apache.org/docs/current/reference/#or-step)
+ [profile( )](http://tinkerpop.apache.org/docs/current/reference/#profile-step)
+ [properties( )](http://tinkerpop.apache.org/docs/current/reference/#properties-step)
+ [subgraph( )](http://tinkerpop.apache.org/docs/current/reference/#subgraph-step)
+ [until( )](http://tinkerpop.apache.org/docs/current/reference/#until-step)
+ [V( )](http://tinkerpop.apache.org/docs/current/reference/#graph-step)
+ [value( )](http://tinkerpop.apache.org/docs/current/reference/#value-step)
+ [valueMap( )](http://tinkerpop.apache.org/docs/current/reference/#valuemap-step)
+ [values( )](http://tinkerpop.apache.org/docs/current/reference/#values-step)

## Étapes Gremlin qui peuvent être converties en opérations natives du moteur Neptune dans certains cas
<a name="gremlin-steps-sometimes"></a>

Certaines étapes Gremlin peuvent être converties en opérations natives du moteur Neptune dans certaines situations, mais pas dans d'autres :
+ [addE( )](http://tinkerpop.apache.org/docs/current/reference/#addedge-step) : l'étape `addE()` peut généralement être convertie en une opération native du moteur Neptune, à moins qu'elle ne soit immédiatement suivie d'une étape `property()` contenant une traversée en tant que clé.
+ [addV( )](http://tinkerpop.apache.org/docs/current/reference/#addvertex-step) : l'étape `addV()` peut généralement être convertie en une opération native du moteur Neptune, à moins qu'elle ne soit immédiatement suivie d'une étape `property()` contenant une traversée en tant que clé ou à moins que plusieurs étiquettes ne soient attribuées.
+ [aggregate( )](http://tinkerpop.apache.org/docs/current/reference/#store-step) : l'étape `aggregate()` peut généralement être convertie en une opération native du moteur Neptune, sauf si elle est utilisée dans une traversée ou une sous-traversée secondaire, ou à moins que la valeur stockée ne soit autre qu'un sommet, une arête, un ID, une étiquette ou une valeur de propriété.

  Dans l'exemple ci-dessous, l'étape `aggregate()` n'est pas convertie, car elle est utilisée dans une traversée enfant :

  ```
  g.V().has('code','ANC').as('a')
       .project('flights').by(select('a')
       .outE().aggregate('x'))
  ```

  Dans cet exemple, l'étape aggregate() n'est pas convertie, car ce qui est stocké est une valeur `min()` :

  ```
  g.V().has('code','ANC').outE().aggregate('x').by(values('dist').min())
  ```
+ [barrier( )](http://tinkerpop.apache.org/docs/current/reference/#barrier-step) : l'étape `barrier()` peut généralement être convertie en une opération native du moteur Neptune, sauf si l'étape qui la suit n'est pas convertie.
+ [cap( )](http://tinkerpop.apache.org/docs/current/reference/#cap-step) : le seul cas où l'étape `cap()` est convertie est lorsqu'elle est combinée à l'étape `unfold()` pour renvoyer une version dépliée d'un agrégat de valeurs de sommet, d'arête, d'ID ou de propriété. Dans cet exemple, `cap()` sera converti, car il est suivi de `.unfold()` :

  ```
  g.V().has('airport','country','IE').aggregate('airport').limit(2)
       .cap('airport').unfold()
  ```

  Toutefois, si vous supprimez `.unfold()`, `cap()` ne sera pas converti :

  ```
  g.V().has('airport','country','IE').aggregate('airport').limit(2)
       .cap('airport')
  ```
+ [coalesce ()](http://tinkerpop.apache.org/docs/current/reference/#coalesce-step) [— Le seul cas où l'`coalesce()`étape est convertie est lorsqu'elle suit le [modèle Upsert](http://tinkerpop.apache.org/docs/current/recipes/#element-existence) recommandé sur la TinkerPop page des recettes.](http://tinkerpop.apache.org/docs/current/recipes/) Les autres modèles coalesce() ne sont pas autorisés. La conversion est limitée au cas où toutes les traversées enfants peuvent être converties, où elles génèremt toutes le même type de sortie (sommet, arête, ID, valeur, clé ou étiquette), où elles mènent toutes à un nouvel élément et où elles ne contiennent pas l'étape `repeat()`.
+ [constant( )](http://tinkerpop.apache.org/docs/current/reference/#constant-step) : l'étape constant() n'est actuellement convertie que si elle est utilisée dans une partie `sack().by()` d'une traversée pour attribuer une valeur de constante, comme ceci :

  ```
  g.V().has('code','ANC').sack(assign).by(constant(10)).out().limit(2)
  ```
+ [cyclicPath( )](http://tinkerpop.apache.org/docs/current/reference/#cyclicpath-step) : l'étape `cyclicPath()` peut généralement être convertie en opération native du moteur Neptune, sauf si l'étape est utilisée avec des modulateurs `by()`, `from()` ou `to()`. Dans les requêtes suivantes, par exemple, `cyclicPath()` n'est pas converti :

  ```
  g.V().has('code','ANC').as('a').out().out().cyclicPath().by('code')
  g.V().has('code','ANC').as('a').out().out().cyclicPath().from('a')
  g.V().has('code','ANC').as('a').out().out().cyclicPath().to('a')
  ```
+ [drop( )](http://tinkerpop.apache.org/docs/current/reference/#drop-step) : l'étape `drop()` peut généralement être convertie en opération native du moteur Neptune, sauf si l'étape est utilisée dans une étape `sideEffect(`) ou `optional()`.
+ [fold ()](http://tinkerpop.apache.org/docs/current/reference/#fold-step) — L'étape fold () ne peut être convertie que dans deux situations, à savoir lorsqu'elle est utilisée selon le [modèle Upsert](http://tinkerpop.apache.org/docs/current/recipes/#element-existence) recommandé sur la [page des TinkerPop recettes](http://tinkerpop.apache.org/docs/current/recipes/) et lorsqu'elle est utilisée dans un `group().by()` contexte comme celui-ci :

  ```
  g.V().has('code','ANC').out().group().by().by(values('code', 'city').fold())
  ```
+  [has ()](http://tinkerpop.apache.org/docs/current/reference/#has-step) — L'étape `has () `peut généralement être convertie en une opération native du moteur Neptune à condition que les requêtes avec `T` utilisent le prédicat `P.eq`, `P.neq` ou `P.Contains`. Attendez-vous à des variations de `has () `qui impliquent que les instances de `P` soient également converties en mode natif, comme `hasId ('id1234')` qui est équivalent à `has (eq, T.id, 'id1234') `. 
+ [id( )](http://tinkerpop.apache.org/docs/current/reference/#id-step) : l'étape `id()` est convertie sauf si elle est utilisée au niveau d'une propriété, comme ceci :

  ```
  g.V().has('code','ANC').properties('code').id()
  ```
+  [MerGee ()](https://tinkerpop.apache.org/docs/current/reference/#mergeedge-step) — L'`mergeE()`étape peut être convertie en une opération native du moteur Neptune si les paramètres (la condition de fusion, `onCreate` `onMatch` et) sont constants (`null`soit une constante, soit une constante, soit une `Map` valeur de `Map` a). `select()` Tous les exemples d'[arêtes ascendantes](https://docs.aws.amazon.com//neptune/latest/userguide/gremlin-efficient-upserts.html#gremlin-upserts-edges) peuvent être convertis. 
+  [mergeV ()](https://tinkerpop.apache.org/docs/current/reference/#mergevertex-step) — L'étape mergeV () peut être convertie en un fonctionnement natif du moteur Neptune si les paramètres (la condition de fusion, `onCreate` et`onMatch`) sont constants (soit une constante, soit une constante`null`, soit une valeur de a). `Map` `select()` `Map` Tous les exemples de [sommets ascendants peuvent être convertis](https://docs.aws.amazon.com//neptune/latest/userguide/gremlin-efficient-upserts.html#gremlin-upserts-vertices). 
+ [order( )](http://tinkerpop.apache.org/docs/current/reference/#order-step) : l'étape `order()` peut généralement être convertie en opération native du moteur Neptune, sauf si l'une des conditions suivantes est vraie :
  + L'étape `order()` se trouve dans une traversée enfant imbriquée, comme ceci :

    ```
    g.V().has('code','ANC').where(V().out().order().by(id))
    ```
  + L'ordre local est utilisé (par exemple, avec `order(local)`).
  + Un comparateur personnalisé est utilisé dans la modulation `by()` pour effectuer le tri. Voici un exemple de l'utilisation de `sack()` :

    ```
    g.withSack(0).
      V().has('code','ANC').
          repeat(outE().sack(sum).by('dist').inV()).times(2).limit(10).
          order().by(sack())
    ```
  + Il existe plusieurs ordres pour le même élément.
+ [project( )](http://tinkerpop.apache.org/docs/current/reference/#project-step) : l'étape `project()` peut généralement être convertie en opération native du moteur Neptune, sauf si le nombre d'instructions `by()` qui suivent `project()` ne correspond pas au nombre d'étiquettes spécifié, comme ici :

  ```
  g.V().has('code','ANC').project('x', 'y').by(id)
  ```
+ [range( )](http://tinkerpop.apache.org/docs/current/reference/#range-step) : l'étape `range()` n'est convertie que lorsque la limite inférieure de la plage en question est égale à zéro (par exemple, `range(0,3)`).
+ [repeat( )](http://tinkerpop.apache.org/docs/current/reference/#repeat-step) : l'étape `repeat()` peut généralement être convertie en opération native du moteur Neptune, sauf si elle est imbriquée dans une autre étape `repeat()`, comme ceci :

  ```
  g.V().has('code','ANC').repeat(out().repeat(out()).times(2)).times(2)
  ```
+ [sack( )](http://tinkerpop.apache.org/docs/current/reference/#sack-step) : l'étape `sack()` peut généralement être convertie en opération native du moteur Neptune, sauf dans les cas suivants :
  + Si un opérateur sack non numérique est utilisé.
  + Si un opérateur sack non numérique autre que `+`, `-`, `mult`, `div`, `min` et `max` est utilisé.
  + Si `sack()` est utilisé dans une étape `where()` pour filtrer les données en fonction d'une valeur sack, comme ici :

    ```
    g.V().has('code','ANC').sack(assign).by(values('code')).where(sack().is('ANC'))
    ```
+ [sum( )](http://tinkerpop.apache.org/docs/current/reference/#sum-step) : l'étape `sum()` peut généralement être convertie en opération native du moteur Neptune, mais pas lorsqu'elle est utilisée pour calculer une somme globale, comme ceci :

  ```
  g.V().has('code','ANC').outE('routes').values('dist').sum()
  ```
+ [union( )](http://tinkerpop.apache.org/docs/current/reference/#union-step) : l'étape `union()` peut être convertie en opération native du moteur Neptune tant qu'il s'agit de la dernière étape de la requête en dehors de l'étape terminale.
+ [unfold ()](http://tinkerpop.apache.org/docs/current/reference/#unfold-step) — L'`unfold()`étape ne peut être convertie en une opération native du moteur Neptune que lorsqu'elle est utilisée selon [le modèle Upsert](http://tinkerpop.apache.org/docs/current/recipes/#element-existence) recommandé sur [TinkerPopla page des recettes](http://tinkerpop.apache.org/docs/current/recipes/), et lorsqu'elle est utilisée conjointement avec `cap()` ceci :

  ```
  g.V().has('airport','country','IE').aggregate('airport').limit(2)
       .cap('airport').unfold()
  ```
+ [where( )](http://tinkerpop.apache.org/docs/current/reference/#where-step) : l'étape `where()` peut généralement être convertie en opération native du moteur Neptune, sauf dans les cas suivants :
  + Lorsque des modulations by() sont utilisées, comme ceci :

    ```
    g.V().hasLabel('airport').as('a')
         .where(gt('a')).by('runways')
    ```
  + Lorsque des opérateurs de comparaison autres que `eq`, `neq`, `within` et `without` sont utilisés.
  + Lorsque des agrégations fournies par l'utilisateur sont utilisées.

## Étapes Gremlin qui sont jamais converties en opérations natives du moteur Neptune
<a name="gremlin-steps-never"></a>

Les étapes Gremlin suivantes sont prises en charge dans Neptune, mais ne sont jamais converties en opérations natives du moteur Neptune. Au lieu de cela, elles sont exécutées par le serveur Gremlin.
+ [choose( )](http://tinkerpop.apache.org/docs/current/reference/#choose-step)
+ [coin( )](http://tinkerpop.apache.org/docs/current/reference/#coin-step)
+ [inject( )](http://tinkerpop.apache.org/docs/current/reference/#inject-step)
+ [match( )](http://tinkerpop.apache.org/docs/current/reference/#match-step)
+ [math( )](http://tinkerpop.apache.org/docs/current/reference/#math-step)
+ [max( )](http://tinkerpop.apache.org/docs/current/reference/#max-step)
+ [mean( )](http://tinkerpop.apache.org/docs/current/reference/#mean-step)
+ [min( )](http://tinkerpop.apache.org/docs/current/reference/#min-step)
+ [option( )](http://tinkerpop.apache.org/docs/current/reference/#option-step)
+ [optional( )](http://tinkerpop.apache.org/docs/current/reference/#optional-step)
+ [path( )](http://tinkerpop.apache.org/docs/current/reference/#path-step)
+ [propertyMap( )](http://tinkerpop.apache.org/docs/current/reference/#propertymap-step)
+ [sample( )](http://tinkerpop.apache.org/docs/current/reference/#sample-step)
+ [skip( )](http://tinkerpop.apache.org/docs/current/reference/#skip-step)
+ [tail( )](http://tinkerpop.apache.org/docs/current/reference/#tail-step)
+ [timeLimit( )](http://tinkerpop.apache.org/docs/current/reference/#timelimit-step)
+ [tree( )](http://tinkerpop.apache.org/docs/current/reference/#tree-step)

## Étapes Gremlin qui ne sont pas du tout prises en charge dans Neptune
<a name="neptune-gremlin-steps-unsupported"></a>

Les étapes Gremlin suivantes ne sont pas du tout prises en charge dans Neptune. Dans la plupart des cas, cela est dû au fait qu'elles nécessitent un `GraphComputer`, ce que Neptune ne prend pas en charge actuellement.
+ [connectedComponent( )](http://tinkerpop.apache.org/docs/current/reference/#connectedcomponent-step)
+ [io( )](http://tinkerpop.apache.org/docs/current/reference/#io-step)
+ [shortestPath( )](http://tinkerpop.apache.org/docs/current/reference/#shortestpath-step)
+ [withComputer( )](http://tinkerpop.apache.org/docs/current/reference/#with-step)
+ [pageRank( )](http://tinkerpop.apache.org/docs/current/reference/#pagerank-step)
+ [peerPressure( )](http://tinkerpop.apache.org/docs/current/reference/#peerpressure-step)
+ [program( )](http://tinkerpop.apache.org/docs/current/reference/#program-step)

L'étape `io()` est partiellement prise en charge, dans la mesure où elle peut être utilisée pour effectuer une opération de type `read()` à partir d'une URL, mais pas une opération de type `write()`.

# Utilisation de Gremlin avec le moteur de requêtes Neptune DFE
<a name="gremlin-with-dfe"></a>

Si vous activez le [moteur de requête alternatif](neptune-dfe-engine.md) de Neptune connu sous le nom de DFE en [mode laboratoire](features-lab-mode.md) (en définissant le paramètre du `neptune_lab_mode` cluster de base de données sur`DFEQueryEngine=enabled`), Neptune traduit G705 queries/traversals en lecture seule en une représentation logique intermédiaire et les exécute sur le moteur DFE chaque fois que cela est possible.

Cependant, le DFE ne prend pas encore en charge toutes les étapes Gremlin. Lorsqu'une étape ne peut pas être exécutée en mode natif sur le DFE, Neptune recourt à nouveau TinkerPop pour exécuter l'étape. Les rapports `explain` et `profile` incluent des avertissements lorsque cela se produit.

# Couverture des étapes de Garmlin en PDF
<a name="gremlin-step-coverage-in-DFE"></a>

 Gremlin DFE est une fonctionnalité en mode laboratoire qui peut être utilisée soit en activant le paramètre de cluster, soit en utilisant l'`Neptune#useDFE`indice de requête. Pour plus d'informations, reportez-vous à la section [Utilisation de Gremlin avec le moteur de requêtes Neptune DFE](https://docs.aws.amazon.com//neptune/latest/userguide/gremlin-with-dfe.html). 

 Les étapes suivantes peuvent être utilisées dans Gremlin DFE. 

## Trajectoire et étapes de traversée :
<a name="DFE-path-and-traversal"></a>

 [asDate ()](https://tinkerpop.apache.org/docs/current/reference/#asDate-step) [https://tinkerpop.apache.org/docs/current/reference/#order-step](https://tinkerpop.apache.org/docs/current/reference/#order-step) [project ()](https://tinkerpop.apache.org/docs/current/reference/#project-step)[, [range ()](https://tinkerpop.apache.org/docs/current/reference/#range-step), [repeat ()](https://tinkerpop.apache.org/docs/current/reference/#repeat-step), [reverse ()](https://tinkerpop.apache.org/docs/current/reference/#reverse-step), [sack ()](https://tinkerpop.apache.org/docs/current/reference/#sack-step), [sample (), [select ()](https://tinkerpop.apache.org/docs/current/reference/#select-step)](https://tinkerpop.apache.org/docs/current/reference/#sample-step), [sideEffect (), split ()](https://tinkerpop.apache.org/docs/current/reference/#sideeffect-step)[, unfold ()](https://tinkerpop.apache.org/docs/current/reference/#split-step)[, union ()](https://tinkerpop.apache.org/docs/current/reference/#unfold-step)](https://tinkerpop.apache.org/docs/current/reference/#union-step) 

## Étapes d'agrégation et de collecte :
<a name="DFE-aggregate-and-collection"></a>

 [agréger (global)](https://tinkerpop.apache.org/docs/current/reference/#aggregate-step), [combiner ()](https://tinkerpop.apache.org/docs/current/reference/#combine-step), [compter ()](https://tinkerpop.apache.org/docs/current/reference/#count-step), [déduplication ()](https://tinkerpop.apache.org/docs/current/reference/#dedup-step), [déduplication (local), pliage ()](https://tinkerpop.apache.org/docs/current/reference/#dedup-step)[, groupe ()](https://tinkerpop.apache.org/docs/current/reference/#fold-step)[, [groupCount](https://tinkerpop.apache.org/docs/current/reference/#groupcount-step) ()](https://tinkerpop.apache.org/docs/current/reference/#group-step), 

## Étapes mathématiques :
<a name="DFE-mathematical"></a>

 [max ()](https://tinkerpop.apache.org/docs/current/reference/#max-step), [moyenne ()](https://tinkerpop.apache.org/docs/current/reference/#mean-step), [min ()](https://tinkerpop.apache.org/docs/current/reference/#min-step), [somme ()](https://tinkerpop.apache.org/docs/current/reference/#sum-step) 

## Étapes de l'élément :
<a name="DFE-element"></a>

 [OtherV ()](https://tinkerpop.apache.org/docs/current/reference/#otherv-step), [ElementMap ()](https://tinkerpop.apache.org/docs/current/reference/#elementmap-step), [élément ()](https://tinkerpop.apache.org/docs/current/reference/#element-step), [v (), out ()](https://tinkerpop.apache.org/docs/current/reference/#graph-step)[, in (), les deux (), OutE (), iNE (), BothE (), OutV (), InV (), BothV (), AutreV (](https://tinkerpop.apache.org/docs/current/reference/#vertex-step)) 

## Étapes de la propriété :
<a name="DFE-property"></a>

 [propriétés ()](https://tinkerpop.apache.org/docs/current/reference/#properties-step), [clé ()](https://tinkerpop.apache.org/docs/current/reference/#key-step), [valueMap ()](https://tinkerpop.apache.org/docs/current/reference/#propertymap-step), [valeur (](https://tinkerpop.apache.org/docs/current/reference/#value-step)) 

## Étapes du filtre :
<a name="DFE-filter"></a>

 [et ()](https://tinkerpop.apache.org/docs/current/reference/#and-step), [coalesce ()](https://tinkerpop.apache.org/docs/current/reference/#coalesce-step), [coin ()](https://tinkerpop.apache.org/docs/current/reference/#coin-step), [has ()](https://tinkerpop.apache.org/docs/current/reference/#has-step), [is ()](https://tinkerpop.apache.org/docs/current/reference/#is-step), [local ()](https://tinkerpop.apache.org/docs/current/reference/#local-step), [none (), not](https://tinkerpop.apache.org/docs/current/reference/#none-step) [()](https://tinkerpop.apache.org/docs/current/reference/#not-step), [ou ()](https://tinkerpop.apache.org/docs/current/reference/#or-step), [où](https://tinkerpop.apache.org/docs/current/reference/#where-step) () 

## Étapes de manipulation des chaînes :
<a name="DFE-string-manipulation"></a>

 [concat ()](https://tinkerpop.apache.org/docs/current/reference/#concat-step) [https://tinkerpop.apache.org/docs/current/reference/#toUpper-step](https://tinkerpop.apache.org/docs/current/reference/#toUpper-step) 

## Prédicats :
<a name="DFE-predicates"></a>
+  [Comparez : eq, neq, lt, lte, gt, gte](https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates) 
+  [Contient : dedans, sans](https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates) 
+  [texTP : se terminant par, contenant,,, notStartingWith non contenant notEndingWith](https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates) 
+  [P : et, ou, entre, à l'extérieur, à l'intérieur](https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates) 

## Limitations
<a name="gremlin-with-dfe-limitations"></a>

 Répéter avec limite. Les libellés contenus dans la procédure de traversée répétée et de déduplication ne sont pas encore pris en charge dans DFE. 

```
// With Limit inside the repeat traversal
  g.V().has('code','AGR').repeat(out().limit(5)).until(has('code','FRA'))
  
  // With Labels inside the repeat traversal
  g.V().has('code','AGR').repeat(out().as('a')).until(has('code','FRA'))
  
  // With Dedup inside the repeat traversal
  g.V().has('code','AGR').repeat(out().dedup()).until(has('code','FRA'))
```

 Les chemins comportant des répétitions imbriquées ou des étapes de branchement ne sont pas encore pris en charge. 

```
// Path with branching steps
  g.V().has('code','AGR').union(identity, outE().inV()).path().by('code')
  
  
  // With nested repeat
  g.V().has('code','AGR').repeat(out().union(identity(), out())).path().by('code')
```

## Entrelacement de la planification des requêtes
<a name="gremlin-with-dfe-interleaving"></a>

Lorsque le processus de conversion identifie une étape Gremlin qui n'a pas d'opérateur DFE natif correspondant, avant de revenir à Tinkerpop, il essaie de trouver d'autres parties de requête intermédiaires pouvant être exécutées nativement sur le moteur DFE. Pour ce faire, il applique une logique d'entrelacement à la traversée de niveau supérieur. De la sorte, les étapes prises en charge sont utilisées dans la mesure du possible.

Toute conversion de requête intermédiaire sans préfixe est représentée à l'aide de `NeptuneInterleavingStep` dans les sorties `explain` et `profile`.

Pour comparer les performances, vous pouvez désactiver l'entrelacement dans une requête, tout en utilisant le moteur DFE pour exécuter la partie avec préfixe. Vous pouvez également utiliser uniquement le TinkerPop moteur pour l'exécution de requêtes sans préfixe. Pour ce faire, vous avez besoin d'un indicateur de requête `disableInterleaving`.

Tout comme l'indicateur de requête [useDFE](gremlin-query-hints-useDFE.md) avec la valeur `false` empêche totalement l'exécution d'une requête sur le DFE, l'indicateur requête `disableInterleaving` avec la valeur `true` désactive l'entrelacement DFE pour la conversion d'une requête. Par exemple :

```
g.with('Neptune#disableInterleaving', true)
 .V().has('genre','drama').in('likes')
```

## Mise à jour de la sortie Gremlin `explain` et `profile`
<a name="gremlin-with-dfe-explain-update"></a>

Gremlin [explain](gremlin-explain.md) fournit des informations sur la traversée optimisée que Neptune utilisera pour exécuter une requête. Consultez l'[exemple de sortie DFE `explain`](gremlin-explain-api.md#gremlin-explain-dfe) pour voir ce à quoi ressemble la sortie `explain` lorsque le moteur DFE est activé.

L'[API Gremlin `profile`](gremlin-profile-api.md) effectue une traversée Gremlin spécifiée, collecte diverses métriques relatives à l'exécution et génère un rapport de profil contenant des informations sur le plan de requête optimisé et les statistiques d'exécution de différents opérateurs. Consultez l'[exemple de sortie DFE `profile`](gremlin-profile-api.md#gremlin-profile-sample-dfe-output) pour voir ce à quoi ressemble la sortie `profile` lorsque le moteur DFE est activé.

**Note**  
Le moteur DFE étant une fonctionnalité expérimentale publiée en mode laboratoire, le format exact de la sortie `explain` et `profile` peut changer.