

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Mengajukan Kueri Grafik Neptune
<a name="access-graph-queries"></a>

Neptune mendukung bahasa kueri grafik berikut untuk mengakses grafik:
+ [Gremlin](https://tinkerpop.apache.org/gremlin.html), didefinisikan oleh [Apache TinkerPop](https://tinkerpop.apache.org/) untuk membuat dan menanyakan grafik properti.

  Sebuah kueri di Gremlin adalah sebuah traversal yang terdiri dari langkah-langkah berlainan, yang masing-masing mengikuti edge ke simpul.

  Lihat [Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md) untuk mempelajari cara menggunakan Gremlin di Neptune, dan [Kepatuhan standar Gremlin di Amazon Neptune](access-graph-gremlin-differences.md) untuk menemukan detail spesifik tentang implementasi Neptune Gremlin.
+ [OpenCypher](access-graph-opencypher.md)adalah bahasa kueri deklaratif untuk grafik properti yang awalnya dikembangkan oleh Neo4j, kemudian bersumber terbuka pada tahun 2015, dan berkontribusi pada proyek [OpenCypher](http://www.opencypher.org/) di bawah lisensi open-source Apache 2. Sintaksnya didokumentasikan dalam spesifikasi [OpenCypher](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf).
+ [SPARQL](https://www.w3.org/TR/sparql11-overview/) adalah bahasa deklaratif berdasarkan grafik pola-pencocokan, untuk mengajukan kueri data [RDF](https://www.w3.org/2001/sw/wiki/RDF). Hal ini didukung oleh [World Wide Web Consortium](https://www.w3.org/).

  Lihat [Mengakses grafik Neptune dengan SPARQL](access-graph-sparql.md) untuk mempelajari cara menggunakan SPARQL di Neptune, dan [Kepatuhan standar SPARQL di Amazon Neptunus](feature-sparql-compliance.md) untuk menemukan detail spesifik tentang implementasi Neptune SPARQL.

**catatan**  
Baik Gremlin dan OpenCypher dapat digunakan untuk menanyakan data grafik properti apa pun yang disimpan di Neptunus, terlepas dari bagaimana itu dimuat.

**Topics**
+ [Antrean kueri di Amazon Neptune](access-graph-queuing.md)
+ [Cache paket kueri di Amazon Neptunus](access-graph-qpc.md)
+ [Menyuntikkan ID Kustom Ke Dalam Gremlin Neptune atau Kueri SPARQL](features-query-id.md)
+ [Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md)
+ [Mengakses Grafik Neptunus dengan OpenCypher](access-graph-opencypher.md)
+ [Mengakses grafik Neptune dengan SPARQL](access-graph-sparql.md)

# Antrean kueri di Amazon Neptune
<a name="access-graph-queuing"></a>

Ketika mengembangkan dan menyesuaikan aplikasi grafik, mengetahui implikasi dari bagaimana kueri diantrekan oleh database akan sangat membantu. Di Amazon Neptune, antrean kueri terjadi sebagai berikut:
+ Jumlah maksimum kueri yang dapat diantrekan per instans, terlepas dari ukuran instans, adalah 8.192. Setiap kueri yang melebihi jumlah tersebut ditolak dan gagal dengan `ThrottlingException`.
+ Jumlah maksimum kueri yang dapat dijalankan pada satu waktu ditentukan oleh jumlah thread pekerja yang ditetapkan, yang umumnya diatur ke dua kali jumlah core CPU virtual (vCPUs) yang tersedia.
+ Latensi kueri menyertakan waktu yang dihabiskan sebuah kueri dalam antrean serta perjalanan memutari jaringan dan waktu yang benar-benar diperlukan kueri untuk dieksekusi.

## Menentukan berapa banyak kueri dalam antrean Anda pada saat tertentu
<a name="access-graph-queuing-count"></a>

`MainRequestQueuePendingRequests` CloudWatch Metrik mencatat jumlah permintaan yang menunggu dalam antrian input dengan perincian lima menit (lihat). [Metrik Neptunus CloudWatch](cw-metrics.md)

Untuk Gremlin, Anda dapat memperoleh jumlah kueri dalam antrean menggunakan nilai `acceptedQueryCount` yang dikembalikan oleh [API status kueri Gremlin](gremlin-api-status.md). Namun, perlu diingat bahwa nilai `acceptedQueryCount` yang dikembalikan oleh [API status kueri SPARQL](sparql-api-status.md) mencakup semua kueri yang diterima sejak server dimulai, termasuk kueri yang telah selesai.

## Bagaimana antrean kueri dapat memengaruhi waktu habis
<a name="access-graph-queuing-timeouts"></a>

Seperti yang dinyatakan di atas, latensi kueri menyertakan waktu yang dihabiskan sebuah kueri dalam antrean serta waktu yang diperlukan kueri untuk dieksekusi.

Karena periode waktu habis kueri umumnya diukur mulai dari ketika memasuki antrean, antrean yang bergerak lambat dapat membuat banyak kueri kehabisan waktu segera setelah keluar dari antrean. Hal ini jelas tidak diinginkan, jadi hindari antrean kueri dalam jumlah besar kecuali kueri tersebut dapat dieksekusi dengan cepat.

# Cache paket kueri di Amazon Neptunus
<a name="access-graph-qpc"></a>

 Ketika kueri dikirimkan ke Neptunus, string kueri diurai, dioptimalkan, dan diubah menjadi rencana kueri, yang kemudian dieksekusi oleh mesin. Aplikasi sering didukung oleh pola kueri umum yang dipakai dengan nilai yang berbeda. Cache rencana kueri dapat mengurangi latensi keseluruhan dengan menyimpan paket kueri dan dengan demikian menghindari penguraian dan pengoptimalan untuk pola berulang tersebut. 

 Query Plan Cache dapat digunakan untuk **OpenCypher**kueri — baik kueri non-parameter maupun parameter. Ini diaktifkan untuk READ, dan untuk HTTP dan Bolt. Ini **tidak** didukung untuk kueri mutasi OC. Ini **tidak** didukung untuk kueri Gremlin atau SPARQL. 

## Cara memaksa mengaktifkan atau menonaktifkan cache rencana kueri
<a name="access-graph-qpc-enable"></a>

 Cache paket kueri diaktifkan secara default untuk kueri berparameter latensi rendah. **Rencana untuk kueri berparameter hanya di-cache ketika latensi lebih rendah dari ambang batas 100 ms.** Perilaku ini dapat diganti berdasarkan per-kueri (diparameterisasi atau tidak) oleh Petunjuk Kueri tingkat kueri. `QUERY:PLANCACHE` Itu perlu digunakan dengan `USING` klausa. Petunjuk kueri menerima `enabled` atau `disabled` sebagai nilai. 

```
# Forcing plan to be cached or reused
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"enabled\" MATCH(n) RETURN n LIMIT 1"
  
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"enabled\" RETURN \$arg" \
  -d "parameters={\"arg\": 123}"
  
# Forcing plan to be neither cached nor reused
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"disabled\" MATCH(n) RETURN n LIMIT 1"
```

## Cara menentukan apakah rencana di-cache atau tidak
<a name="access-graph-qpc-status"></a>

 Untuk HTTP READ, jika kueri dikirimkan dan paket di-cache, `explain` akan menampilkan detail yang relevan dengan cache rencana kueri. 

```
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"enabled\" MATCH(n) RETURN n LIMIT 1" \
  -d "explain=[static|details]"

Query: <QUERY STRING>
Plan cached by request: <REQUEST ID OF FIRST TIME EXECUTION>
Plan cached at: <TIMESTAMP OF FIRST TIME EXECUTION>
Parameters: <PARAMETERS, IF QUERY IS PARAMETERIZED QUERY>
Plan cache hits: <NUMBER OF CACHE HITS FOR CACHED PLAN>
First query evaluation time: <LATENCY OF FIRST TIME EXECUTION>

The query has been executed based on a cached query plan. Detailed explain with operator runtime statistics can be obtained by running the query with plan cache disabled (using HTTP parameter planCache=disabled).
```

 Saat menggunakan Bolt, fitur jelaskan tidak didukung. 

## Penggusuran
<a name="access-graph-qpc-eviction"></a>

 Rencana kueri diusir oleh cache time to live (TTL) atau ketika jumlah maksimum paket kueri cache telah tercapai. Saat paket kueri terpukul, TTL disegarkan. Defaultnya adalah: 
+  1000 - Jumlah maksimum paket yang dapat di-cache per instance. 
+  TTL - 300.000 milidetik atau 5 menit. Cache hit memulai ulang TTL, dan mengatur ulang kembali ke 5 menit. 

## Kondisi yang menyebabkan rencana tidak di-cache
<a name="access-graph-qpc-conditions"></a>

 Cache paket kueri tidak akan digunakan dalam kondisi berikut: 

1.  Saat kueri dikirimkan menggunakan petunjuk `QUERY:PLANCACHE "disabled"` kueri. Anda dapat menjalankan kembali kueri dan menghapus `QUERY:PLANCACHE "disabled"` untuk mengaktifkan cache rencana kueri. 

1.  Jika kueri yang dikirimkan bukan kueri berparameter dan tidak berisi petunjuk. `QUERY:PLANCACHE "enabled"` 

1.  Jika waktu evaluasi kueri lebih besar dari ambang latensi, kueri tidak di-cache dan dianggap sebagai kueri yang berjalan lama yang tidak akan mendapat manfaat dari cache paket kueri. 

1.  Jika kueri berisi pola yang tidak mengembalikan hasil apa pun. 
   +  yaitu `MATCH (n:nonexistentLabel) return n` ketika ada nol node dengan label yang ditentukan. 
   +  yaitu `MATCH (n {name: $param}) return n` dengan `parameters={"param": "abcde"}` ketika ada nol node yang mengandung`name=abcde`. 

1.  Jika parameter kueri adalah tipe komposit, seperti a `list` atau a`map`. 

   ```
   curl -k https://<endpoint>:<port>/opencypher \
     -d "query=Using QUERY:PLANCACHE \"enabled\" RETURN \$arg" \
     -d "parameters={\"arg\": [1, 2, 3]}"
   
   curl -k https://<endpoint>:<port>/opencypher \
     -d "query=Using QUERY:PLANCACHE \"enabled\" RETURN \$arg" \
     -d "parameters={\"arg\": {\"a\": 1}}"
   ```

1.  Jika parameter query adalah string yang belum menjadi bagian dari beban data atau operasi penyisipan data. Misalnya, jika `CREATE (n {name: "X"})` dijalankan untuk menyisipkan`"X"`, `RETURN "X"` maka di-cache, sementara tidak `RETURN "Y"` akan di-cache, karena `"Y"` belum dimasukkan dan tidak ada dalam database. 

# Menyuntikkan ID Kustom Ke Dalam Gremlin Neptune atau Kueri SPARQL
<a name="features-query-id"></a>

Secara default, Neptune memberikan nilai `queryId` yang unik untuk setiap kueri. Anda dapat menggunakan ID ini untuk mendapatkan informasi tentang kueri yang berjalan (lihat [API status kueri Gremlin](gremlin-api-status.md) atau [API status kueri SPARQL](sparql-api-status.md)), atau membatalkannya (lihat [Pembatalan kueri Gremlin](gremlin-api-status-cancel.md) atau [Pembatalan kueri SPARQL](sparql-api-status-cancel.md)).

Neptune juga memungkinkan Anda menentukan nilai `queryId` sendiri untuk kueri Gremlin atau SPARQL, baik di header HTTP, atau untuk kueri SPARQL menggunakan petunjuk kueri `queryId`. Menugaskan `queryID` Anda sendiri memudahkan pelacakan kueri untuk mendapatkan statusnya atau membatalkannya.

## Menyuntikkan Nilai `queryId` Kustom Menggunakan Header HTTP
<a name="features-query-id-header"></a>

Untuk Gremlin dan SPARQL, header HTTP dapat digunakan untuk menyuntikkan nilai `queryId` Anda sendiri ke dalam kueri.

**Contoh Gremlin**

```
curl -XPOST https://your-neptune-endpoint:port \
    -d "{\"gremlin\": \
        \"g.V().limit(1).count()\" , \
        \"queryId\":\"4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47\"  }"
```

**Contoh SPARQL**

```
curl https://your-neptune-endpoint:port/sparql \
    -d "query=SELECT * WHERE { ?s ?p ?o } " \
       --data-urlencode \
       "queryId=4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47"
```

## Menyuntikkan Nilai `queryId` Kustom menggunakan Petunjuk Kueri SPARQL
<a name="features-query-id-hint"></a>

Berikut adalah contoh bagaimana Anda akan menggunakan petunjuk kueri `queryId` SPARQL untuk menyuntikkan nilai `queryId` kustom ke dalam kueri SPARQL:

```
curl https://your-neptune-endpoint:port/sparql \
    -d "query=PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#> \
       SELECT * WHERE { hint:Query hint:queryId \"4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47\" \
       {?s ?p ?o}}"
```

## Menggunakan Nilai `queryId` untuk Memeriksa Status Kueri
<a name="features-query-id-check-status"></a>

**Contoh Gremlin**

```
curl https://your-neptune-endpoint:port/gremlin/status \
    -d "queryId=4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47"
```

**Contoh SPARQL**

```
curl https://your-neptune-endpoint:port/sparql/status \
    -d "queryId=4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47"
```

# Mengakses grafik Neptune dengan Gremlin
<a name="access-graph-gremlin"></a>

Amazon Neptunus kompatibel dengan TinkerPop Apache dan Gremlin. Ini berarti Anda dapat terhubung ke instans DB Neptunus dan menggunakan bahasa traversal Gremlin untuk menanyakan grafik ([lihat](https://tinkerpop.apache.org/docs/current/reference/#graph) Grafik dalam dokumentasi Apache). TinkerPop Untuk perbedaan dalam implementasi Neptune Gremlin, lihat [Kepatuhan standar Gremlin](access-graph-gremlin-differences.md).

 Sebuah *traversal* di Gremlin adalah serangkaian langkah berantai. Traversal dimulai pada sebuah vertex (atau edge). Traversal menelusuri grafik dengan mengikuti edge keluar dari setiap vertex lalu edge keluar dari vertex tersebut. Setiap langkah adalah operasi dalam traversal. Untuk informasi selengkapnya, lihat [The Traversal](https://tinkerpop.apache.org/docs/current/reference/#traversal) dalam TinkerPop dokumentasi.

Versi mesin Neptune yang berbeda mendukung versi Gremlin yang berbeda. Periksa [halaman rilis mesin](engine-releases.md) versi Neptunus yang Anda jalankan untuk menentukan rilis Gremlin mana yang didukungnya atau lihat tabel berikut yang mencantumkan versi paling awal dan terbaru yang TinkerPop didukung oleh versi mesin Neptunus yang berbeda:


| Versi Mesin Neptune |  TinkerPop Versi Minimum |  TinkerPop Versi Maksimum | 
| --- | --- | --- | 
| `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 klien biasanya kompatibel ke belakang dalam seri (`3.6.x`, misalnya, atau`3.7.x`) dan sementara mereka sering dapat bekerja melintasi batas-batas tersebut, tabel di atas merekomendasikan kombinasi versi untuk digunakan untuk pengalaman dan kompatibilitas terbaik. Kecuali disarankan lain, umumnya yang terbaik adalah mematuhi pedoman ini dan meningkatkan aplikasi klien agar sesuai dengan versi yang TinkerPop Anda gunakan.

Saat memutakhirkan TinkerPop versi, selalu penting untuk merujuk ke [TinkerPopdokumentasi pemutakhiran](http://tinkerpop.apache.org/docs/current/upgrade/) yang akan membantu Anda mengidentifikasi fitur baru yang dapat Anda manfaatkan, tetapi juga masalah yang mungkin perlu Anda waspadai saat mendekati peningkatan. Anda biasanya mengharapkan kueri dan fitur yang ada berfungsi setelah peningkatan kecuali sesuatu secara khusus disebut sebagai masalah untuk dipertimbangkan. Terakhir, penting untuk dicatat bahwa jika versi yang Anda tingkatkan untuk memiliki fitur baru, Anda mungkin tidak dapat menggunakannya jika berasal dari versi yang lebih lambat dari yang didukung Neptunus.

Ada beberapa varian bahasa Gremlin dan dukungan untuk akses Gremlin dalam berbagai bahasa pemrograman. Untuk informasi selengkapnya, lihat [Tentang Varian Bahasa Gremlin](https://tinkerpop.apache.org/docs/current/reference/#gremlin-drivers-variants) dalam dokumentasi. TinkerPop 

Dokumentasi ini menjelaskan cara mengakses Neptunus dengan varian dan bahasa pemrograman berikut:
+ [Mengatur konsol Gremlin agar terhubung ke instans DB Neptune](access-graph-gremlin-console.md)
+ [Menggunakan titik akhir HTTPS REST untuk menyambung ke instans DB Neptune](access-graph-gremlin-rest.md)
+ [Klien Gremlin berbasis Java untuk digunakan dengan Amazon Neptunus](access-graph-gremlin-client.md)
+ [Menggunakan Python untuk terhubung ke instans DB Neptune](access-graph-gremlin-python.md)
+ [Gunakan .NET untuk terhubung ke instans DB Neptune](access-graph-gremlin-dotnet.md)
+ [Gunakan Node.js untuk terhubung ke instans DB Neptune](access-graph-gremlin-node-js.md)
+ [Menggunakan Go untuk terhubung ke instans DB Neptunus](access-graph-gremlin-go.md)

Seperti dibahas dalam[Mengenkripsi koneksi ke database Amazon Neptunus Anda dengan SSL/HTTPS](security-ssl.md), Anda harus menggunakan Transport Layer Security/Secure Sockets Layer (TLS/SSL) saat menghubungkan ke Neptunus di semua Wilayah. AWS 

Sebelum Anda mulai, Anda harus memiliki yang berikut:
+ Instans DB Neptune. Untuk informasi tentang membuat instans DB Neptune, lihat [Membuat cluster Amazon Neptunus](get-started-create-cluster.md).
+ Instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

Untuk informasi lebih lanjut tentang memuat data ke dalam Neptune, termasuk prasyarat, format pemuatan, dan parameter beban, lihat [Memuat data ke Amazon Neptune](load-data.md).

**Topics**
+ [Mengatur konsol Gremlin agar terhubung ke instans DB Neptune](access-graph-gremlin-console.md)
+ [Menggunakan titik akhir HTTPS REST untuk menyambung ke instans DB Neptune](access-graph-gremlin-rest.md)
+ [Klien Gremlin berbasis Java untuk digunakan dengan Amazon Neptunus](access-graph-gremlin-client.md)
+ [Menggunakan Python untuk terhubung ke instans DB Neptune](access-graph-gremlin-python.md)
+ [Gunakan .NET untuk terhubung ke instans DB Neptune](access-graph-gremlin-dotnet.md)
+ [Gunakan Node.js untuk terhubung ke instans DB Neptune](access-graph-gremlin-node-js.md)
+ [Menggunakan Go untuk terhubung ke instans DB Neptunus](access-graph-gremlin-go.md)
+ [Menggunakan AWS SDK untuk menjalankan kueri Gremlin](access-graph-gremlin-sdk.md)
+ [Petunjuk kueri Gremlin](gremlin-query-hints.md)
+ [API status kueri Gremlin](gremlin-api-status.md)
+ [Pembatalan kueri Gremlin](gremlin-api-status-cancel.md)
+ [Support untuk sesi berbasis skrip Gremlin](access-graph-gremlin-sessions.md)
+ [Transaksi Gremlin di Neptunus](access-graph-gremlin-transactions.md)
+ [Menggunakan API Gremlin dengan Amazon Neptune](gremlin-api-reference.md)
+ [Hasil kueri cache di Amazon Neptunus Gremlin](gremlin-results-cache.md)
+ [Membuat peningkatan yang efisien dengan `mergeV()` Gremlin dan langkah-langkah `mergeE()`](gremlin-efficient-upserts.md)
+ [Membuat peningkatan Gremlin yang efisien dengan `fold()/coalesce()/unfold()`](gremlin-efficient-upserts-pre-3.6.md)
+ [Menganalisis eksekusi kueri Neptune menggunakan `explain` Gremlin](gremlin-explain.md)
+ [Menggunakan Gremlin dengan mesin kueri Neptunus DFE](gremlin-with-dfe.md)

# Mengatur konsol Gremlin agar terhubung ke instans DB Neptune
<a name="access-graph-gremlin-console"></a>

Konsol Gremlin memungkinkan Anda bereksperimen dengan TinkerPop grafik dan kueri di lingkungan REPL (loop). read-eval-print 

## Menginstal konsol Gremlin dan menghubungkannya dengan cara biasa
<a name="access-graph-gremlin-console-usual-connect"></a>

Anda dapat menggunakan Konsol Gremlin untuk terhubung ke basis data grafik jarak jauh. Bagian berikut memandu Anda melalui penginstalan dan konfigurasi Konsol Gremlin untuk menghubungkan ke instans DB Neptune secara jarak jauh. Anda harus mengikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

Untuk bantuan menghubungkan ke Neptunus SSL/TLS dengan (yang diperlukan), lihat. [Konfigurasi SSL/TLS](access-graph-gremlin-java.md#access-graph-gremlin-java-ssl)

**catatan**  
Jika [autentikasi IAM diaktifkan](iam-auth-enable.md) di cluster DB Neptunus Anda, ikuti petunjuk [Menghubungkan ke database Amazon Neptunus menggunakan otentikasi IAM dengan konsol Gremlin](iam-auth-connecting-gremlin-console.md) untuk menginstal konsol Gremlin daripada instruksi di sini.

**Untuk memasang Konsol Gremlin dan menyambung ke Neptune**

1. Biner Konsol Gremlin memerlukan Java 8 atau Java 11. Instruksi ini mengasumsikan penggunaan Java 11. Anda dapat menginstal Java 11 pada instans EC2 Anda sebagai berikut:
   + Jika Anda menggunakan [Amazon Linux 2 (AL2)](https://aws.amazon.com/amazon-linux-2):

     ```
     sudo amazon-linux-extras install java-openjdk11
     ```
   + Jika Anda menggunakan [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
     ```
   + Untuk distribusi lain, gunakan salah satu dari berikut ini yang sesuai:

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

     atau:

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

1. Masukkan yang berikut ini untuk mengatur Java 11 sebagai runtime default pada instans EC2 Anda.

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

   Saat diminta, masukkan nomor untuk Java 11.

1. Unduh versi Konsol Gremlin yang sesuai dari situs web Apache. Anda dapat memeriksa versi Gremlin mana yang didukung versi Neptunus Anda. [Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md) Misalnya, jika Anda memerlukan versi 3.7.2, Anda dapat mengunduh [konsol Gremlin](https://archive.apache.org/dist/tinkerpop/3.7.2/apache-tinkerpop-gremlin-console-3.7.2-bin.zip) dari situs web [Apache Tinkerpop](https://tinkerpop.apache.org/download.html) ke instans EC2 Anda seperti ini:

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

1. Unzip file Konsol Gremlin.

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

1. Ubah direktori ke dalam direktori yang di-unzip.

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

1. Di sudirektori `conf` dari direktori yang diekstrak, buat sebuah file bernama `neptune-remote.yaml` dengan teks berikut. Ganti *your-neptune-endpoint* dengan nama host atau alamat IP instans DB Neptunus Anda. Tanda kurung persegi (`[ ]`) wajib diisi.
**catatan**  
Untuk informasi tentang menemukan nama host instans DB Neptune Anda, lihat bagian [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md).

   ```
   hosts: [your-neptune-endpoint]
   port: 8182
   connectionPool: { enableSsl: true }
   serializer: { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1,
                 config: { serializeResultToString: true }}
   ```
**catatan**  
 Serializer dipindahkan dari `gremlin-driver` modul ke `gremlin-util` modul baru di versi 3.7.0. Paket diubah dari org.apache.tinkerpop.gremlin.driver.ser menjadi org.apache.tinkerpop.gremlin.util.ser. 

1. Di terminal, bernavigasilah ke direktori Konsol Gremlin (`apache-tinkerpop-gremlin-console-3.7.2`), lalu masukkan perintah berikut untuk menjalankan Konsol Gremlin.

   ```
   bin/gremlin.sh
   ```

   Anda akan melihat output berikut:

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

   Anda sekarang berada di prompt `gremlin>`. Anda akan memasukkan langkah-langkah yang tersisa pada prompt ini.

1. Di prompt `gremlin>`, masukkan hal berikut untuk menyambung ke instans DB Neptune.

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

1. Di prompt `gremlin>`, masukkan hal berikut ini untuk beralih ke mode jarak jauh. Ini mengirimkan semua kueri Gremlin ke koneksi remote.

   ```
   :remote console
   ```

1. Masukkan hal berikut untuk mengirim kueri ke Gremlin Graph.

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

1. Setelah Anda selesai, masukkan hal berikut untuk keluar dari Konsol Gremlin.

   ```
   :exit
   ```

**catatan**  
Gunakan titik koma (`;`) atau karakter baris baru (`\n`) untuk memisahkan setiap pernyataan.   
Setiap traversal sebelum traversal akhir harus diakhiri dengan `next()` yang akan dieksekusi. Hanya data dari traversal akhir yang dikembalikan.

Untuk informasi lebih lanjut tentang implementasi Neptune dari Gremlin, lihat [Kepatuhan standar Gremlin di Amazon Neptune](access-graph-gremlin-differences.md).

# Cara alternatif untuk terhubung ke konsol Gremlin
<a name="access-graph-gremlin-console-connect"></a>

**Kelemahan dari pendekatan koneksi normal**

Cara paling umum untuk terhubung ke konsol Gremlin adalah yang dijelaskan di atas, menggunakan perintah seperti ini pada `gremlin>` prompt:

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

Ini berfungsi dengan baik, dan memungkinkan Anda mengirim kueri ke Neptunus. Namun, itu mengeluarkan mesin skrip Groovy dari loop, jadi Neptunus memperlakukan semua kueri sebagai Gremlin murni. Ini berarti bahwa formulir kueri berikut gagal:

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

Yang paling dekat yang bisa Anda dapatkan menggunakan variabel saat terhubung dengan cara ini adalah dengan menggunakan `result` variabel yang dikelola oleh konsol dan mengirim kueri menggunakan`:>`, seperti ini:

```
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]
```

 

**Cara berbeda untuk terhubung**

Anda juga dapat terhubung ke konsol Gremlin dengan cara yang berbeda, yang mungkin Anda temukan lebih bagus, seperti ini:

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

Di sini `neptune.properties` mengambil formulir ini:

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

`my-cluster.yaml`File akan terlihat seperti ini:

```
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 }
```

**catatan**  
 Serializer dipindahkan dari `gremlin-driver` modul ke `gremlin-util` modul baru di versi 3.7.0. Paket diubah dari org.apache.tinkerpop.gremlin.driver.ser menjadi org.apache.tinkerpop.gremlin.util.ser. 

Mengkonfigurasi koneksi konsol Gremlin seperti itu memungkinkan Anda membuat jenis kueri berikut dengan sukses:

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

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

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

Anda dapat menghindari menampilkan hasilnya, seperti ini:

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

Semua cara kueri yang biasa (tanpa langkah terminal) terus berfungsi. Contoh:

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

Anda bahkan dapat menggunakan [https://tinkerpop.apache.org/docs/current/reference/#io-step](https://tinkerpop.apache.org/docs/current/reference/#io-step)langkah untuk memuat file dengan koneksi semacam ini.

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

Neptunus [mendukung otentikasi IAM](iam-auth-enable.md) untuk mengontrol akses ke cluster DB Anda. Jika autentikasi IAM diaktifkan, Anda harus menggunakan penandatanganan Signature Version 4 untuk mengautentikasi permintaan Anda. Untuk instruksi terperinci dan contoh kode untuk menghubungkan dari konsol Gremlin, lihat. [Menghubungkan ke database Amazon Neptunus menggunakan otentikasi IAM dengan konsol Gremlin](iam-auth-connecting-gremlin-console.md)

# Menggunakan titik akhir HTTPS REST untuk menyambung ke instans DB Neptune
<a name="access-graph-gremlin-rest"></a>

Amazon Neptune menyediakan titik akhir HTTPS untuk kueri Gremlin. Antarmuka REST kompatibel dengan apa pun versi Gremlin yang digunakan klaster DB Anda (lihat [halaman rilis mesin](engine-releases.md) dari versi mesin Neptune yang Anda jalankan untuk menentukan rilis Gremlin yang didukungnya).

**catatan**  
Sebagaimana dibahas dalam [Mengenkripsi koneksi ke database Amazon Neptunus Anda dengan SSL/HTTPS](security-ssl.md), Neptune sekarang mengharuskan Anda terhubung menggunakan HTTPS dan bukan HTTP. Selain itu, Neptunus saat ini tidak mendukung HTTP/2 untuk permintaan REST API. Klien harus menggunakan HTTP/1.1 saat menghubungkan ke titik akhir.

Petunjuk berikut memandu Anda menyambung ke titik akhir Gremlin menggunakan perintah `curl` dan HTTPS. Anda harus mengikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

Titik akhir HTTPS untuk kueri Gremlin ke instans DB Neptune adalah `https://your-neptune-endpoint:port/gremlin`.

**catatan**  
Untuk informasi tentang menemukan nama host instans DB Neptune Anda, lihat [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md).

## Untuk menyambung ke Neptune menggunakan titik akhir HTTP REST
<a name="access-graph-gremlin-rest-connect"></a>

Contoh berikut menggunakan **curl** untuk mengirimkan kueri Gremlin melalui **POST** HTTP. Kueri dikirimkan dalam format JSON dalam tubuh posting sebagai properti `gremlin`.

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

Contoh ini mengembalikan vertex pertama dalam grafik menggunakan traversal `g.V().limit(1)`. Anda dapat mengajukan kueri untuk sesuatu yang lain dengan menggantinya dengan traversal Gremlin lain.

**penting**  
Secara default, titik akhir REST mengembalikan semua hasil dalam satu set hasil JSON. Jika set hasil ini terlalu besar, pengecualian `OutOfMemoryError` dapat terjadi pada instans DB Neptune.  
Anda dapat menghindari hal ini dengan mengaktifkan respons bongkahan (hasil dikembalikan dalam serangkaian respons terpisah). Lihat [Gunakan header jejak HTTP opsional untuk mengaktifkan respons multi-bagian Gremlin](access-graph-gremlin-rest-trailing-headers.md).

Meskipun permintaan **POST** HTTP direkomendasikan untuk mengirim kueri Gremlin, tetapi memungkinkan juga untuk menggunakan permintaan **GET** HTTP:

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

**catatan**  
Neptune tidak mendukung properti `bindings`.

# Gunakan header jejak HTTP opsional untuk mengaktifkan respons multi-bagian Gremlin
<a name="access-graph-gremlin-rest-trailing-headers"></a>

Secara default, respons HTTP untuk kueri Gremlin dikembalikan dalam satu set hasil JSON. Dalam kasus set hasil yang sangat besar, ini dapat menyebabkan pengecualian `OutOfMemoryError` pada instans DB.

Namun, Anda dapat mengaktifkan respons *bongkahan* (respons yang dikembalikan dalam beberapa bagian yang terpisah). Anda melakukan ini dengan menyertakan header jejak transfer-encoding (TE) (`te: trailers`) dalam permintaan Anda. Lihat [halaman MDN tentang header permintaan TE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/TE)) untuk informasi lebih lanjut tentang header TE.

Ketika respons dikembalikan dalam beberapa bagian, akan sulit untuk mendiagnosis masalah yang terjadi setelah bagian pertama diterima, karena bagian pertama tiba dengan kode status HTTP `200` (OK). Kegagalan berikutnya biasanya menghasilkan badan pesan yang berisi respons yang rusak, pada akhirnya Neptune menambahkan pesan kesalahan.

Agar deteksi dan diagnosis kegagalan semacam ini jadi lebih mudah, Neptune juga mencakup dua bidang header baru dalam trailing header dari setiap bongkahan respons:
+ `X-Neptune-Status`  –   berisi kode respons diikuti dengan nama pendek. Misalnya, dalam kasus keberhasilan, trailing header akan berupa: `X-Neptune-Status: 200 OK`. Dalam kasus kegagalan, kode respon akan menjadi salah satu [kode kesalahan mesin Neptune](errors-engine-codes.md), seperti `X-Neptune-Status: 500 TimeLimitExceededException`.
+ `X-Neptune-Detail`  –   kosong untuk permintaan yang berhasil. Dalam kasus kesalahan, ia berisi pesan kesalahan JSON. Karena hanya karakter ASCII yang diperbolehkan dalam nilai header HTTP, string JSON di-enkode dengan URL.

**catatan**  
Neptune saat ini tidak mendukung kompresi `gzip` respons bongkahan. Jika klien meminta kedua encoding bongkahan dan kompresi pada saat yang sama, Neptune melewatkan kompresi.

# Klien Gremlin berbasis Java untuk digunakan dengan Amazon Neptunus
<a name="access-graph-gremlin-client"></a>

[Anda dapat menggunakan salah satu dari dua klien Gremlin berbasis Java open-source dengan Amazon Neptunus: klien [Apache TinkerPop Java Gremlin, atau klien Gremlin](https://search.maven.org/artifact/org.apache.tinkerpop/gremlin-driver) untuk Amazon Neptunus.](https://search.maven.org/artifact/software.amazon.neptune/gremlin-client)

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

Apache TinkerPop Java [gremlin-driver](https://tinkerpop.apache.org/docs/current/reference/#gremlin-java) adalah standar, klien Gremlin resmi yang bekerja dengan database grafik -enabled. TinkerPop Gunakan klien ini ketika Anda membutuhkan kompatibilitas maksimum dengan ruang TinkerPop pengembangan yang lebih luas, saat Anda bekerja dengan beberapa sistem database grafik, atau ketika Anda tidak memerlukan manajemen cluster lanjutan dan fitur load balancing khusus untuk Neptunus. Klien ini juga cocok untuk aplikasi sederhana yang terhubung ke satu instance Neptunus atau ketika Anda lebih suka menangani load balancing di tingkat infrastruktur daripada di dalam klien.

**penting**  
Memilih versi driver Apache TinkerPop Gremlin yang benar sangat penting untuk kompatibilitas dengan versi mesin Neptunus Anda. Menggunakan versi yang tidak kompatibel dapat mengakibatkan kegagalan koneksi atau perilaku yang tidak terduga. Untuk informasi kompatibilitas versi terperinci, lihat[Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md).

**catatan**  
Tabel yang membantu Anda menentukan TinkerPop versi Apache yang benar untuk digunakan dengan Neptunus telah dipindahkan ke. [Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md) Tabel ini sebelumnya terletak di halaman ini selama bertahun-tahun dan sekarang lebih terpusat untuk referensi untuk semua bahasa pemrograman yang TinkerPop mendukung.

## Klien Gremlin Java untuk Amazon Neptunus
<a name="access-graph-neptune-gremlin-client"></a>

Klien Gremlin untuk Amazon Neptunus adalah klien [Gremlin berbasis Java open-source yang bertindak sebagai pengganti drop-in](https://github.com/aws/neptune-gremlin-client) untuk klien Java standar. TinkerPop 

Klien Neptunus Gremlin dioptimalkan untuk cluster Neptunus. Ini memungkinkan Anda mengelola distribusi lalu lintas di beberapa instance dalam sebuah cluster, dan beradaptasi dengan perubahan topologi cluster saat Anda menambahkan atau menghapus replika. Anda bahkan dapat mengonfigurasi klien untuk mendistribusikan permintaan di seluruh subset instance di klaster Anda, berdasarkan peran, tipe instans, zona ketersediaan (AZ), atau tag yang terkait dengan instance.

[Versi terbaru dari klien Neptunus Gremlin Java tersedia di Maven](https://search.maven.org/artifact/software.amazon.neptune/gremlin-client) Central.

[Untuk informasi lebih lanjut tentang klien Neptunus Gremlin Java, lihat posting blog ini.](https://aws.amazon.com/blogs/database/load-balance-graph-queries-using-the-amazon-neptune-gremlin-client/) Untuk contoh kode dan demo, lihat [ GitHub proyek klien](https://github.com/aws/neptune-gremlin-client).

Saat memilih versi klien Neptunus Gremlin, Anda perlu mempertimbangkan versi yang TinkerPop mendasarinya sehubungan dengan versi mesin Neptunus Anda. Lihat tabel kompatibilitas di [Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md) untuk menentukan TinkerPop versi yang benar untuk mesin Neptunus Anda, lalu gunakan tabel berikut untuk memilih versi klien Neptunus Gremlin yang sesuai:


**Kompatibilitas versi klien Neptunus Gremlin**  

| Versi klien Neptunus Gremlin | TinkerPop versi | 
| --- | --- | 
| 3.x | 3.7.x (AWS SDK for Java 2.x/1.x) | 
| 2.1.x | 3.7.x (AWS SDK for Java 1.x) | 
| 2.0.x | 3.6.x | 
| 1.12 | 3.5.x | 

# Menggunakan klien Java untuk terhubung ke instance DB Neptunus
<a name="access-graph-gremlin-java"></a>

Bagian berikut memandu Anda melalui menjalankan sampel Java lengkap yang terhubung ke instance DB Neptunus dan melakukan traversal Gremlin menggunakan klien Apache Gremlin. TinkerPop

Anda harus mengikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

**Untuk menyambung ke Neptune menggunakan Java**

1. Install Apache Maven pada instans EC2 Anda. Jika menggunakan Amazon Linux 2023 (lebih disukai), gunakan:

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

   Jika menggunakan Amazon Linux 2, unduh biner terbaru dari [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. **Instal Java.** Perpustakaan Gremlin membutuhkan Java 8 atau 11. Anda dapat menginstal Java 11 sebagai berikut:
   + Jika Anda menggunakan [Amazon Linux 2 (AL2)](https://aws.amazon.com/amazon-linux-2):

     ```
     sudo amazon-linux-extras install java-openjdk11
     ```
   + Jika Anda menggunakan [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
     ```
   + Untuk distribusi lain, gunakan salah satu dari berikut ini yang sesuai:

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

     atau:

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

1. **Setel Java 11 sebagai runtime default pada instans EC2 Anda:** Masukkan yang berikut ini untuk menetapkan Java 8 sebagai runtime default pada instans EC2 Anda:

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

   Saat diminta, masukkan nomor untuk Java 11.

1. **Buat direktori baru bernama`gremlinjava`:**

   ```
   mkdir gremlinjava
   cd gremlinjava
   ```

1.  Di direktori `gremlinjava`, buat file `pom.xml`, lalu buka file tersebut dalam editor teks:

   ```
   nano pom.xml
   ```

1. Salin JSON berikut ke dalam file `pom.xml` dan simpan filenya:

   ```
   <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>
   ```
**catatan**  
Jika Anda memodifikasi proyek Maven yang ada, dependensi yang diperlukan disorot dalam kode sebelumnya.

1. Buat subdirektori untuk kode sumber contoh (`src/main/java/com/amazonaws/`) dengan mengetik teks berikut pada baris perintah:

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

1. Di direktori `src/main/java/com/amazonaws/`, buat file bernama `App.java`, lalu buka file tersebut dalam editor teks.

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

1. Salin hal berikut ke dalam file `App.java`. Ganti *your-neptune-endpoint* dengan alamat instans DB Neptunus Anda. *Jangan* sertakan prefiks `https://` di metode `addContactPoint`.
**catatan**  
Untuk informasi tentang menemukan nama host instans DB Neptune Anda, lihat [Menghubungkan ke Titik Akhir 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();
     }
   }
   ```

   Untuk bantuan menghubungkan ke Neptunus SSL/TLS dengan (yang diperlukan), lihat. [Konfigurasi SSL/TLS](#access-graph-gremlin-java-ssl)

1. Kompilasikan dan jalankan sampel menggunakan perintah Maven berikut:

   ```
   mvn compile exec:exec
   ```

Contoh sebelumnya mengembalikan peta kunci dan nilai-nilai masing-masing properti untuk dua vertex pertama dalam grafik menggunakan traversal `g.V().limit(3).elementMap()`. Untuk mengajukan kueri untuk sesuatu yang lain, ganti dengan traversal Gremlin lain dengan salah satu metode ending yang tepat.

**catatan**  
Bagian akhir dari kueri Gremlin, `.toList()`, diperlukan untuk mengirimkan traversal ke server untuk evaluasi. Jika Anda tidak menyertakan metode tersebut atau metode setara lain, kueri tidak diserahkan ke instans DB Neptune.  
Anda juga harus menambahkan ending yang tepat ketika Anda menambahkan sebuah vertex atau edge, seperti ketika Anda menggunakan langkah `addV( )`.

Metode berikut mengirimkan kueri ke instans DB Neptune:
+ `toList()`
+ `toSet()`
+ `next()`
+ `nextTraverser()`
+ `iterate()`

## Konfigurasi SSL/TLS untuk klien Gremlin Java
<a name="access-graph-gremlin-java-ssl"></a>

Neptunus harus diaktifkan SSL/TLS secara default. Biasanya, jika driver Java dikonfigurasi dengan`enableSsl(true)`, ia dapat terhubung ke Neptunus tanpa harus mengatur `keyStore()` atau `trustStore()` dengan salinan lokal sertifikat.

Namun, jika instans yang Anda sambungkan tidak memiliki koneksi internet untuk memverifikasi sertifikat publik, atau jika sertifikat yang Anda gunakan tidak bersifat publik, Anda dapat mengambil langkah-langkah berikut untuk mengonfigurasi salinan sertifikat lokal:

**Menyiapkan salinan sertifikat lokal untuk mengaktifkan SSL/TLS**

1. Unduh dan instal [keytool](https://docs.oracle.com/javase/9/tools/keytool.htm#JSWOR-GUID-5990A2E4-78E3-47B7-AE75-6D1826259549) dari Oracle. Ini akan membuat pengaturan toko kunci lokal jauh lebih mudah.

1. Unduh sertifikat `SFSRootCAG2.pem` CA (Gremlin Java SDK memerlukan sertifikatuntuk memverifikasi sertifikat jarak jauh):

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

1. Buat toko kunci dalam JKS atau PKCS12 format. Contoh ini menggunakan JKS. Jawab pertanyaan-pertanyaan yang mengikuti pada prompt. Kata sandi yang Anda buat di sini akan dibutuhkan nanti:

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

1. Impor `SFSRootCAG2.pem` file yang Anda unduh ke toko kunci yang baru dibuat:

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

1. Konfigurasikan `Cluster` objek secara terprogram:

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

   Anda dapat melakukan hal yang sama dalam file konfigurasi jika Anda mau, seperti yang mungkin Anda lakukan dengan konsol 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 }}
   ```

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

Neptunus [mendukung otentikasi IAM](iam-auth-enable.md) untuk mengontrol akses ke cluster DB Anda. Jika autentikasi IAM diaktifkan, Anda harus menggunakan penandatanganan Signature Version 4 untuk mengautentikasi permintaan Anda. Untuk petunjuk rinci dan contoh kode untuk menghubungkan dari klien Java, lihat[Menghubungkan ke database Amazon Neptunus menggunakan IAM dengan Gremlin Java](iam-auth-connecting-gremlin-java.md).

# Contoh Java tentang menghubungkan ke instans DB Neptune dengan logika sambungan ulang
<a name="access-graph-gremlin-java-reconnect-example"></a>

Contoh Java berikut menunjukkan cara terhubung ke klien Gremlin dengan logika sambungan ulang untuk pulih dari pemutusan sambungan tak terduga.

Contoh ini memiliki dependensi berikut:

```
<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>
```

Berikut adalah kode sampelnya:

**penting**  
 `CallExecutor`Dari Retry4j mungkin tidak aman untuk utas. Pertimbangkan agar setiap utas menggunakan `CallExecutor` instancenya sendiri, atau gunakan pustaka percobaan ulang yang berbeda. 

**catatan**  
 Contoh berikut telah diperbarui untuk menyertakan penggunaan requestInterceptor (). Ini ditambahkan di TinkerPop 3.6.6. Sebelum TinkerPop versi 3.6.6, contoh kode menggunakan HandshakeInterceptor (), yang tidak digunakan lagi dengan rilis itu. 

```
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;
  };
}
```

# Menggunakan Python untuk terhubung ke instans DB Neptune
<a name="access-graph-gremlin-python"></a>

**penting**  
Memilih versi driver Apache TinkerPop Gremlin yang benar sangat penting untuk kompatibilitas dengan versi mesin Neptunus Anda. Menggunakan versi yang tidak kompatibel dapat mengakibatkan kegagalan koneksi atau perilaku yang tidak terduga. Untuk informasi kompatibilitas versi terperinci, lihat[Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md).

Bagian berikut memandu Anda melalui proses berjalannya sampel Python yang menyambungkan ke instans Amazon Neptune DB dan melakukan traversal Gremlin.

Anda harus mengikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

Sebelum memulai, lakukan hal berikut:
+ Unduh dan pasang Python 3.6 atau yang lebih baru dari [Situs web Python.org](https://www.python.org/downloads/).
+ Pastikan Anda memiliki **pip** diinstal. Jika Anda tidak punya **pip** atau Anda tidak yakin, lihat [Apakah saya perlu menginstal pip?](https://pip.pypa.io/en/stable/installing/#do-i-need-to-install-pip) di dokumentasi **pip**.
+ Jika instalasi Python Anda belum memilikinya, unduh `futures` seperti berikut: `pip install futures`



**Untuk menyambung ke Neptune menggunakan Python**

1. Masukkan hal berikut untuk menginstal paket `gremlinpython`:

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

1. Buat file bernama `gremlinexample.py`, lalu buka file tersebut dalam editor teks.

1. Salin hal berikut ke dalam file `gremlinexample.py`. Ganti *your-neptune-endpoint* dengan alamat cluster DB Neptunus Anda *your-neptune-port* dan dengan port cluster DB Neptunus Anda (default:8182). 

   Untuk informasi tentang menemukan alamat instans DB Neptune Anda, lihat bagian [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md).

    Contoh di bawah ini menunjukkan bagaimana untuk terhubung dengan Gremlin 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. Masukkan perintah berikut untuk menjalankan sampel:

   ```
   python gremlinexample.py
   ```

   Kueri Gremlin pada akhir contoh ini mengembalikan vertex (`g.V().limit(2)`) dalam daftar. Daftar ini kemudian dicetak dengan fungsi `print` standar Python.
**catatan**  
Bagian akhir dari kueri Gremlin, `toList()`, diperlukan untuk mengirimkan traversal ke server untuk evaluasi. Jika Anda tidak menyertakan metode tersebut atau metode setara lain, kueri tidak diserahkan ke instans DB Neptune.

   Metode berikut mengirimkan kueri ke instans DB Neptune:
   + `toList()`
   + `toSet()`
   + `next()`
   + `nextTraverser()`
   + `iterate()`

   

   Contoh sebelumnya mengembalikan dua vertex pertama dalam grafik menggunakan traversal `g.V().limit(2).toList()`. Untuk mengajukan kueri untuk sesuatu yang lain, ganti dengan traversal Gremlin lain dengan salah satu metode ending yang tepat.

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

Neptunus [mendukung otentikasi IAM](iam-auth-enable.md) untuk mengontrol akses ke cluster DB Anda. Jika autentikasi IAM diaktifkan, Anda harus menggunakan penandatanganan Signature Version 4 untuk mengautentikasi permintaan Anda. Untuk petunjuk rinci dan contoh kode untuk menghubungkan dari klien Python, lihat. [Menghubungkan ke database Amazon Neptunus menggunakan otentikasi IAM dengan Python Gremlin](gremlin-python-iam-auth.md)

# Gunakan .NET untuk terhubung ke instans DB Neptune
<a name="access-graph-gremlin-dotnet"></a>

**penting**  
Memilih versi driver Apache TinkerPop Gremlin yang benar sangat penting untuk kompatibilitas dengan versi mesin Neptunus Anda. Menggunakan versi yang tidak kompatibel dapat mengakibatkan kegagalan koneksi atau perilaku yang tidak terduga. Untuk informasi kompatibilitas versi terperinci, lihat[Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md).

Bagian berikut berisi contoh kode yang ditulis dalam C\$1 yang menyambung ke instans DB Neptune dan melakukan traversal Gremlin.

Sambungan ke Amazon Neptune harus berasal dari Instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda. Kode sampel ini diuji pada instans Amazon EC2 yang menjalankan Ubuntu.

Sebelum memulai, lakukan hal berikut:
+ Instal .NET pada instans Amazon EC2. Untuk mendapatkan petunjuk cara menginstal .NET di beberapa sistem operasi, termasuk Windows, Linux, dan macOS, lihat [Memulai dengan .NET](https://www.microsoft.com/net/learn/get-started/).
+ Instal Gremlin.NET dengan menjalankan `dotnet add package gremlin.net` untuk paket Anda. Untuk informasi selengkapnya, lihat [Gremlin.net di dokumentasi](https://tinkerpop.apache.org/docs/current/reference/#gremlin-DotNet). TinkerPop 



**Untuk menyambung ke Neptune menggunakan Gremlin.NET**

1. Buat proyek .NET baru.

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

1. Ubah direktori ke direktori proyek baru.

   ```
   cd gremlinExample
   ```

1. Salin hal berikut ke dalam file `Program.cs`. Ganti *your-neptune-endpoint* dengan alamat instans DB Neptunus Anda.

   Untuk informasi tentang menemukan alamat instans DB Neptune Anda, lihat bagian [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md).

   ```
   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. Masukkan perintah berikut untuk menjalankan sampel:

   ```
   dotnet run
   ```

   Kueri Gremlin pada akhir contoh ini mengembalikan jumlah vertex tunggal untuk tujuan pengujian. Ini kemudian dicetak ke konsol.
**catatan**  
Bagian akhir dari kueri Gremlin, `Next()`, diperlukan untuk mengirimkan traversal ke server untuk evaluasi. Jika Anda tidak menyertakan metode tersebut atau metode setara lain, kueri tidak diserahkan ke instans DB Neptune.

   Metode berikut mengirimkan kueri ke instans DB Neptune:
   + `ToList()`
   + `ToSet()`
   + `Next()`
   + `NextTraverser()`
   + `Iterate()`

   Gunakan `Next()` jika Anda membutuhkan hasil kueri agar diserialkan dan dikembalikan, atau `Iterate()` jika tidak.

   Contoh sebelumnya mengembalikan daftar dengan menggunakan traversal. `g.V().Limit(3).ToList()` Untuk mengajukan kueri untuk sesuatu yang lain, ganti dengan traversal Gremlin lain dengan salah satu metode ending yang tepat.

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

Neptunus [mendukung otentikasi IAM](iam-auth-enable.md) untuk mengontrol akses ke cluster DB Anda. Jika autentikasi IAM diaktifkan, Anda harus menggunakan penandatanganan Signature Version 4 untuk mengautentikasi permintaan Anda. Untuk petunjuk rinci dan contoh kode untuk menghubungkan dari klien.NET, lihat[Menghubungkan ke database Amazon Neptunus menggunakan otentikasi IAM dengan Gremlin.NET](gremlin-dotnet-iam-auth.md).

# Gunakan Node.js untuk terhubung ke instans DB Neptune
<a name="access-graph-gremlin-node-js"></a>

**penting**  
Memilih versi driver Apache TinkerPop Gremlin yang benar sangat penting untuk kompatibilitas dengan versi mesin Neptunus Anda. Menggunakan versi yang tidak kompatibel dapat mengakibatkan kegagalan koneksi atau perilaku yang tidak terduga. Untuk informasi kompatibilitas versi terperinci, lihat[Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md).

Bagian berikut memandu Anda melalui proses berjalannya sampel Node.js yang menyambungkan ke instans Amazon Neptune DB dan melakukan traversal Gremlin.

Anda harus mengikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

Sebelum memulai, lakukan hal berikut:
+ Pastikan Node.js versi 8.11 atau lebih tinggi yang diinstal. Jika bukan, unduh dan instal Node.js dari [Situs web Nodejs.org](https://nodejs.org).

**Untuk menyambung ke Neptune menggunakan Node.js**

1. Masukkan hal berikut untuk menginstal paket `gremlin-javascript`:

   ```
   npm install gremlin
   ```

1. Buat file bernama `gremlinexample.js`, lalu buka file tersebut dalam editor teks.

1. Salin hal berikut ke dalam file `gremlinexample.js`. Ganti *your-neptune-endpoint* dengan alamat instans DB Neptunus Anda.

   Untuk informasi tentang menemukan alamat instans DB Neptune Anda, lihat bagian [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md).

   ```
   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. Masukkan perintah berikut untuk menjalankan sampel:

   ```
   node gremlinexample.js
   ```

Contoh sebelumnya mengembalikan jumlah vertex tunggal dalam grafik menggunakan traversal `g.V().limit(1).count().next()`. Untuk mengajukan kueri untuk sesuatu yang lain, ganti dengan traversal Gremlin lain dengan salah satu metode ending yang tepat.

**catatan**  
Bagian akhir dari kueri Gremlin, `next()`, diperlukan untuk mengirimkan traversal ke server untuk evaluasi. Jika Anda tidak menyertakan metode tersebut atau metode setara lain, kueri tidak diserahkan ke instans DB Neptune.

Metode berikut mengirimkan kueri ke instans DB Neptune:
+ `toList()`
+ `toSet()`
+ `next()`
+ `nextTraverser()`
+ `iterate()`

Gunakan `next()` jika Anda membutuhkan hasil kueri agar diserialkan dan dikembalikan, atau `iterate()` jika tidak.

**penting**  
Ini adalah contoh Node.js mandiri. Jika Anda berencana untuk menjalankan kode seperti ini dalam suatu AWS Lambda fungsi, lihat [Contoh fungsi Lambda](lambda-functions-examples.md) detail tentang penggunaan JavaScript secara efisien dalam fungsi Lambda Neptunus.

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

Neptunus [mendukung otentikasi IAM](iam-auth-enable.md) untuk mengontrol akses ke cluster DB Anda. Jika autentikasi IAM diaktifkan, Anda harus menggunakan penandatanganan Signature Version 4 untuk mengautentikasi permintaan Anda. Untuk instruksi terperinci dan contoh kode untuk menghubungkan dari JavaScript klien, lihat[Menghubungkan ke database Amazon Neptunus menggunakan otentikasi IAM dengan Gremlin JavaScript](gremlin-javascript-iam-auth.md).

# Menggunakan Go untuk terhubung ke instans DB Neptunus
<a name="access-graph-gremlin-go"></a>

**penting**  
Memilih versi driver Apache TinkerPop Gremlin yang benar sangat penting untuk kompatibilitas dengan versi mesin Neptunus Anda. Menggunakan versi yang tidak kompatibel dapat mengakibatkan kegagalan koneksi atau perilaku yang tidak terduga. Untuk informasi kompatibilitas versi terperinci, lihat[Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md).

**catatan**  
Versi 3.5.x gremlingo kompatibel dengan versi 3.4.x selama Anda hanya menggunakan TinkerPop fitur 3.4.x dalam kueri Gremlin yang Anda tulis.

Bagian berikut memandu Anda melalui menjalankan sampel Go yang terhubung ke instans Amazon Neptunus DB dan melakukan traversal Gremlin.

Anda harus mengikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

Sebelum memulai, lakukan hal berikut:
+ Unduh dan instal Go 1.17 atau yang lebih baru dari situs web [go.dev.](https://go.dev/dl/)

**Untuk terhubung ke Neptunus menggunakan Go**

1. Mulai dari direktori kosong, inisialisasi modul Go baru:

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

1. Tambahkan gremlin-go sebagai dependensi modul baru Anda:

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

1. Buat file bernama `gremlinExample.go` dan kemudian buka di editor teks.

1. Salin yang berikut ini ke dalam `gremlinExample.go` file, ganti *`(your neptune endpoint)`* dengan alamat instans DB Neptunus Anda:

   ```
   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())
     }
   }
   ```
**catatan**  
Format sertifikat Neptunus TLS saat ini tidak didukung di Go 1.18\$1 dengan macOS, dan mungkin memberikan kesalahan 509 saat mencoba memulai koneksi. Untuk pengujian lokal, ini dapat dilewati dengan menambahkan “crypto/tls” ke impor dan memodifikasi pengaturan sebagai berikut: `DriverRemoteConnection`  

   ```
   // 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. Masukkan perintah berikut untuk menjalankan sampel:

   ```
   go run gremlinExample.go
   ```

Query Gremlin di akhir contoh ini mengembalikan simpul `(g.V().Limit(2))` dalam irisan. Irisan ini kemudian diulang dan dicetak dengan `fmt.Println` fungsi standar.

**catatan**  
Bagian akhir dari kueri Gremlin, `ToList()`, diperlukan untuk mengirimkan traversal ke server untuk evaluasi. Jika Anda tidak menyertakan metode tersebut atau metode setara lain, kueri tidak diserahkan ke instans DB Neptune.

Metode berikut mengirimkan kueri ke instans DB Neptune:
+ `ToList()`
+ `ToSet()`
+ `Next()`
+ `GetResultSet()`
+ `Iterate()`

Contoh sebelumnya mengembalikan dua vertex pertama dalam grafik menggunakan traversal `g.V().Limit(2).ToList()`. Untuk mengajukan kueri untuk sesuatu yang lain, ganti dengan traversal Gremlin lain dengan salah satu metode ending yang tepat.

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

Neptunus [mendukung otentikasi IAM](iam-auth-enable.md) untuk mengontrol akses ke cluster DB Anda. Jika autentikasi IAM diaktifkan, Anda harus menggunakan penandatanganan Signature Version 4 untuk mengautentikasi permintaan Anda. Untuk petunjuk rinci dan contoh kode untuk menghubungkan dari klien Go, lihat[Menghubungkan ke database Amazon Neptunus menggunakan otentikasi IAM dengan Gremlin Go](gremlin-go-iam-auth.md).

# Menggunakan AWS SDK untuk menjalankan kueri Gremlin
<a name="access-graph-gremlin-sdk"></a>

Dengan AWS SDK, Anda dapat menjalankan kueri Gremlin terhadap grafik Neptunus Anda menggunakan bahasa pemrograman pilihan Anda. Neptunus data API SDK (`neptunedata`nama layanan) menyediakan tindakan untuk mengirimkan kueri [ExecuteGremlinQuery](https://docs.aws.amazon.com/neptune/latest/data-api/API_ExecuteGremlinQuery.html)Gremlin.

Anda harus menjalankan contoh ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama dengan cluster DB Neptunus Anda, atau dari lokasi yang memiliki konektivitas jaringan ke titik akhir cluster Anda.

Tautan langsung ke dokumentasi referensi API untuk `neptunedata` layanan di setiap bahasa SDK dapat ditemukan di bawah ini:


| Bahasa pemrograman | referensi 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) | 
| Karat | [https://crates.io/crates/aws-sdk-neptunedata](https://crates.io/crates/aws-sdk-neptunedata) | 
| CLI | [https://docs.aws.amazon.com/cli/latest/reference/neptunedata/](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/) | 

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

Contoh berikut menunjukkan cara menyiapkan `neptunedata` klien, menjalankan kueri Gremlin, dan mencetak hasilnya. Ganti *YOUR\$1NEPTUNE\$1HOST* dan *YOUR\$1NEPTUNE\$1PORT* dengan titik akhir dan port cluster DB Neptunus Anda.

**Konfigurasi batas waktu sisi klien dan coba lagi**  
Batas waktu klien SDK mengontrol berapa lama *klien* menunggu respons. Itu tidak mengontrol berapa lama kueri berjalan di server. Jika waktu klien habis sebelum server selesai, kueri dapat terus berjalan di Neptunus sementara klien tidak memiliki cara untuk mengambil hasilnya.  
Sebaiknya atur batas waktu baca sisi klien ke `0` (tanpa batas waktu) atau ke nilai yang setidaknya beberapa detik lebih lama dari pengaturan neptune\$1query\$1timeout sisi server di cluster DB [Neptunus](parameters.md#parameters-db-cluster-parameters-neptune_query_timeout) Anda. Ini memungkinkan Neptunus mengontrol saat waktu kueri habis.  
Kami juga merekomendasikan pengaturan upaya coba ulang maksimum ke `1` (tidak ada percobaan ulang). Jika SDK mencoba ulang kueri yang masih berjalan di server, itu dapat menghasilkan operasi duplikat. Ini sangat penting untuk kueri mutasi, di mana percobaan lagi dapat menyebabkan duplikat penulisan yang tidak diinginkan.

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

1. 4. Ikuti [instruksi instalasi](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) untuk menginstal Boto3.

1. Buat file bernama `gremlinExample.py` dan tempel kode berikut:

   ```
   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. Jalankan contoh: `python gremlinExample.py`

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

1. Ikuti [petunjuk penginstalan](https://docs.aws.amazon.com//sdk-for-java/latest/developer-guide/setup.html) untuk menyiapkan AWS SDK for Java.

1. Gunakan kode berikut untuk menyiapkan`NeptunedataClient`, menjalankan kueri Gremlin, dan mencetak hasilnya:

   ```
   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. Ikuti [petunjuk penginstalan](https://docs.aws.amazon.com//sdk-for-javascript/v3/developer-guide/getting-started-nodejs.html) untuk menyiapkan AWS SDK. JavaScript Instal paket klien neptunedata:. `npm install @aws-sdk/client-neptunedata`

1. Buat file bernama `gremlinExample.js` dan tempel kode berikut:

   ```
   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. Jalankan contoh: `node gremlinExample.js`

------

# Petunjuk kueri Gremlin
<a name="gremlin-query-hints"></a>

Gunakan petunjuk kueri untuk menentukan optimasi dan evaluasi strategi untuk kueri Gremlin tertentu di Amazon Neptune. 

Petunjuk kueri ditentukan dengan menambahkan langkah `withSideEffect` untuk kueri dengan sintaks berikut.

```
g.withSideEffect(hint, value)
```
+ *petunjuk* – Mengidentifikasi jenis petunjuk yang akan diterapkan.
+ *nilai* – Menentukan perilaku aspek sistem yang sedang dipertimbangkan.

Sebagai contoh, hal berikut ini menunjukkan bagaimana cara memasukkan petunjuk `repeatMode`dalam traversal Gremlin.

**catatan**  
Semua efek samping petunjuk kueri Gremlin diprefiks dengan `Neptune#`.

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

Kueri sebelumnya menginstruksikan mesin Neptune untuk melakukan traversal pada grafik *Depth First* (`DFS`) ketimbang Neptune default, *Breadth First* (`BFS`).

Bagian berikut menyediakan informasi selengkapnya tentang petunjuk kueri yang tersedia dan penggunaannya.

**Topics**
+ [Petunjuk kueri repeatMode Gremlin](gremlin-query-hints-repeatMode.md)
+ [Petunjuk kueri noReordering Gremlin](gremlin-query-hints-noReordering.md)
+ [Petunjuk permintaan TypePromotion Gremlin](gremlin-query-hints-typePromotion.md)
+ [Petunjuk kueri useDFE Gremlin](gremlin-query-hints-useDFE.md)
+ [Petunjuk kueri Gremlin untuk menggunakan cache hasil](gremlin-query-hints-results-cache.md)

# Petunjuk kueri repeatMode Gremlin
<a name="gremlin-query-hints-repeatMode"></a>

Petunjuk kueri `repeatMode` Neptune menentukan bagaimana mesin Neptune mengevaluasi langkah `repeat()` dalam traversal Gremlin: breadth first, depth first, atau chunked depth first.

Mode evaluasi langkah `repeat()` penting ketika digunakan untuk menemukan atau mengikuti jalur, bukan hanya mengulangi langkah dalam jumlah pengulangan terbatas.

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

Petunjuk kueri `repeatMode` ditentukan dengan menambahkan langkah `withSideEffect` untuk kueri.

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

**catatan**  
Semua efek samping petunjuk kueri Gremlin diprefiks dengan `Neptune#`.

**Mode yang Tersedia**
+ `BFS`

  Pencarian Breadth-First

  Mode eksekusi default untuk langkah `repeat()`. Ini mendapat semua node saudara sebelum pergi lebih dalam sepanjang jalur.

  Versi ini intensif memori dan perbatasan bisa menjadi sangat besar. Ada risiko yang lebih tinggi bahwa kueri akan kehabisan memori dan dibatalkan oleh mesin Neptune. Ini paling cocok dengan implementasi Gremlin lainnya.
+ `DFS`

  Pencarian Depth-First

  Mengikuti setiap jalur ke kedalaman maksimum sebelum beralih ke solusi berikutnya.

  Ini menggunakan lebih sedikit memori. Ini dapat memberikan performa yang lebih baik dalam situasi seperti menemukan jalur tunggal dari titik awal ke beberapa hop.
+ `CHUNKED_DFS`

  Pencarian Chunked Depth-First

  Pendekatan hibrida yang mengeksplorasi depth-first grafik dalam potongan 1.000 node, bukan 1 node (`DFS`) atau semua node (`BFS)`).

  Mesin Neptune akan mendapatkan hingga 1.000 node pada setiap tingkat sebelum mengikuti jalur yang lebih dalam.

  Ini adalah pendekatan yang seimbang antara kecepatan dan penggunaan memori. 

  Hal ini juga berguna jika Anda ingin menggunakan `BFS`, tapi kueri menggunakan terlalu banyak memori.



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

Bagian berikut menjelaskan efek dari mode pengulangan pada traversal Gremlin.

Di Neptune, mode default untuk langkah `repeat()` adalah untuk melakukan strategi eksekusi breadth-first (`BFS`) untuk semua traversal. 

Dalam kebanyakan kasus, TinkerGraph implementasi menggunakan strategi eksekusi yang sama, tetapi dalam beberapa kasus mengubah eksekusi traversal. 

Misalnya, TinkerGraph implementasi memodifikasi query berikut.

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

Langkah `repeat()` dalam traversal ini di-“unrolled” ke dalam traversal berikut, yang menghasilkan strategi depth-first (`DFS`).

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

**penting**  
Mesin permintaan Neptune tidak melakukan ini secara otomatis.

Breadth-first (`BFS`) adalah strategi eksekusi default, dan mirip dengan TinkerGraph dalam kebanyakan kasus. Namun, ada kasus-kasus tertentu di mana strategi depth (`DFS`) lebih baik.

 

**BFS (Default)**  
Breadth-first (BFS) adalah strategi eksekusi default untuk operator `repeat()`.

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

Mesin Neptune sepenuhnya mengeksplorasi perbatasan sembilan hop pertama sebelum menemukan sepuluh hop solusi. Hal ini efektif dalam banyak kasus, seperti kueri jalur terpendek.

Namun, untuk contoh sebelumnya, traversal akan jauh lebih cepat menggunakan mode depth-first (`DFS`) untuk operator `repeat()`.

**DFS**  
Kueri berikut menggunakan mode depth-first (`DFS`) untuk operator `repeat()`.

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

Ini mengikuti setiap solusi individu ke kedalaman maksimum sebelum menjelajahi solusi berikutnya. 

# Petunjuk kueri noReordering Gremlin
<a name="gremlin-query-hints-noReordering"></a>

Ketika Anda mengirimkan traversal Gremlin, mesin kueri Neptune menyelidiki struktur traversal dan mengurutkan ulang bagian dari kueri, mencoba untuk meminimalkan jumlah pekerjaan yang diperlukan untuk evaluasi dan waktu respons kueri. Sebagai contoh, sebuah traversal dengan beberapa kendala, seperti beberapa langkah `has()`, biasanya tidak dievaluasi dalam urutan yang diberikan. Sebaliknya traversal diurutkan ulang setelah kueri diperiksa dengan analisis statis.

Mesin kueri Neptune mencoba untuk mengidentifikasi kendala mana yang lebih selektif dan menjalankannya terlebih dulu. Hal ini sering menghasilkan performa yang lebih baik, tetapi urutan yang dipilih Neptune untuk mengevaluasi kueri mungkin tidak selalu optimal.

Jika Anda tahu karakteristik data yang tepat dan ingin secara manual mendikte urutan eksekusi kueri, Anda dapat menggunakan petunjuk kueri `noReordering` Neptune untuk menentukan bahwa traversal dievaluasi dalam urutan yang diberikan.

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

Petunjuk kueri `noReordering` ditentukan dengan menambahkan langkah `withSideEffect` untuk kueri.

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

**catatan**  
Semua efek samping petunjuk kueri Gremlin diprefiks dengan `Neptune#`.

**Nilai yang Tersedia**
+ `true`
+ `false`

# Petunjuk permintaan TypePromotion Gremlin
<a name="gremlin-query-hints-typePromotion"></a>

Ketika Anda mengirimkan traversal Gremlin yang memfilter di atas nilai atau jangkauan numerik, mesin kueri Neptune biasanya harus menggunakan promosi jenis ketika mengeksekusi kueri. Ini berarti bahwa mesin harus memeriksa nilai-nilai dari setiap jenis yang dapat memegang nilai yang Anda gunakan untuk menyaring.

Misalnya, jika Anda menyaring untuk nilai yang sama dengan 55, mesin harus mencari bilangan bulat yang sama dengan 55, bilangan bulat panjang sama dengan 55L, mengapung sama dengan 55.0, dan sebagainya. Setiap promosi jenis memerlukan pencarian tambahan pada penyimpanan, yang dapat menyebabkan permintaan yang tampaknya sederhana tiba-tiba mengambil waktu yang lama untuk menyelesaikan.

Katakanlah Anda sedang mencari semua vertex dengan properti customer-age lebih besar dari 5:

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

Untuk mengeksekusi traversal yang secara menyeluruh, Neptune harus memperluas kueri untuk memeriksa setiap jenis numerik yang dapat mempromosikan nilai Anda kueri. Dalam hal ini, filter `gt` harus diterapkan untuk setiap integer lebih dari 5, setiap panjang lebih dari 5L, setiap float lebih dari 5.0, dan setiap ganda lebih 5.0. Karena masing-masing promosi jenis ini memerlukan pencarian tambahan pada penyimpanan, Anda akan melihat beberapa filter per filter numerik ketika Anda menjalankan [API `profile` Gremlin](gremlin-profile-api.md) untuk kueri ini, dan akan memakan waktu lebih lama untuk menyelesaikan dari yang mungkin Anda harapkan.

Sering kali promosi jenis tidak perlu karena Anda tahu sebelumnya bahwa Anda hanya perlu menemukan nilai dari satu jenis tertentu. Ketika hal ini terjadi, Anda dapat mempercepat kueri Anda secara dramatis dengan menggunakan petunjuk kueri `typePromotion` untuk mematikan promosi jenis.

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

Petunjuk kueri `typePromotion` ditentukan dengan menambahkan langkah `withSideEffect` untuk kueri.

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

**catatan**  
Semua efek samping petunjuk kueri Gremlin diprefiks dengan `Neptune#`.

**Nilai yang Tersedia**
+ `true`
+ `false`

Untuk menonaktifkan promosi jenis untuk kueri di atas, Anda akan menggunakan:

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

# Petunjuk kueri useDFE Gremlin
<a name="gremlin-query-hints-useDFE"></a>

Gunakan petunjuk kueri ini untuk mengaktifkan penggunaan DFE untuk mengeksekusi kueri. [Secara default Neptunus tidak menggunakan DFE tanpa petunjuk kueri ini disetel ke, karena parameter instance neptune\$1dfe\$1query\$1engine default `true` ke.](parameters.md#parameters-instance-parameters-neptune_dfe_query_engine) `viaQueryHint` Jika Anda menyetel parameter instance itu`enabled`, mesin DFE digunakan untuk semua kueri kecuali yang memiliki petunjuk `useDFE` kueri yang disetel ke. `false`

Contoh mengaktifkan DFE untuk kueri:

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

# Petunjuk kueri Gremlin untuk menggunakan cache hasil
<a name="gremlin-query-hints-results-cache"></a>

Petunjuk kueri berikut dapat digunakan saat [cache hasil kueri](gremlin-results-cache.md) diaktifkan.

## Petunjuk kueri Gremlin `enableResultCache`
<a name="gremlin-query-hints-results-cache-enableResultCache"></a>

Petunjuk `enableResultCache` kueri dengan nilai `true` menyebabkan hasil kueri dikembalikan dari cache jika sudah di-cache. Jika tidak, ia mengembalikan hasil baru dan men-cache mereka sampai waktu mereka dihapus dari cache. Contoh:

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

Kemudian, Anda dapat mengakses hasil cache dengan mengeluarkan kueri yang persis sama lagi.

Jika nilai petunjuk kueri ini`false`, atau jika tidak ada, hasil kueri tidak di-cache. Namun, menyetelnya ke `false` tidak menghapus hasil cache yang ada. Untuk menghapus hasil cache, gunakan `invalidateResultCachekey` petunjuk `invalidateResultCache` atau.

## Petunjuk kueri Gremlin `enableResultCacheWithTTL`
<a name="gremlin-query-hints-results-cache-enableResultCacheWithTTL"></a>

Petunjuk `enableResultCacheWithTTL` kueri juga mengembalikan hasil cache jika ada, tanpa mempengaruhi TTL hasil yang sudah ada di cache. Jika saat ini tidak ada hasil cache, kueri mengembalikan hasil baru dan menyimpannya dalam cache untuk waktu hidup (TTL) yang ditentukan oleh petunjuk `enableResultCacheWithTTL` kueri. Waktu untuk hidup ditentukan dalam hitungan detik. Misalnya, kueri berikut menentukan waktu untuk hidup enam puluh detik:

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

Sebelum 60 detik time-to-live selesai, Anda dapat menggunakan kueri yang sama (di sini,`g.V().has('genre','drama').in('likes')`) dengan petunjuk `enableResultCache` atau `enableResultCacheWithTTL` kueri untuk mengakses hasil yang di-cache.

**catatan**  
Waktu untuk hidup ditentukan dengan `enableResultCacheWithTTL` tidak mempengaruhi hasil yang telah di-cache.  
Jika hasil sebelumnya di-cache menggunakan`enableResultCache`, cache harus terlebih dahulu dihapus secara eksplisit sebelum `enableResultCacheWithTTL` menghasilkan hasil baru dan menyimpannya untuk TTL yang ditentukannya.
Jika hasil sebelumnya di-cache menggunakan`enableResultCachewithTTL`, TTL sebelumnya harus kedaluwarsa terlebih dahulu sebelum `enableResultCacheWithTTL` menghasilkan hasil baru dan menyimpannya untuk TTL yang ditentukannya.

Setelah waktu untuk hidup berlalu, hasil cache untuk kueri dihapus, dan contoh berikutnya dari kueri yang sama kemudian mengembalikan hasil baru. Jika `enableResultCacheWithTTL` dilampirkan ke kueri berikutnya, hasil baru di-cache dengan TTL yang ditentukannya.

## Petunjuk kueri Gremlin `invalidateResultCacheKey`
<a name="gremlin-query-hints-results-cache-invalidateResultCacheKey"></a>

Petunjuk `invalidateResultCacheKey` kueri dapat mengambil `false` nilai `true` atau. `true`Nilai menyebabkan hasil cache untuk kueri yang `invalidateResultCacheKey` dilampirkan akan dihapus. Misalnya, contoh berikut menyebabkan hasil cache `g.V().has('genre','drama').in('likes')` untuk kunci kueri dihapus:

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

Contoh kueri di atas tidak menyebabkan hasil barunya di-cache. Anda dapat menyertakan `enableResultCache` (atau`enableResultCacheWithTTL`) dalam kueri yang sama jika Anda ingin menyimpan hasil baru setelah menghapus hasil cache yang ada:

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

## Petunjuk kueri Gremlin `invalidateResultCache`
<a name="gremlin-query-hints-results-cache-invalidateResultCache"></a>

Petunjuk `invalidateResultCache` kueri dapat mengambil `false` nilai `true` atau. `true`Nilai menyebabkan semua hasil dalam cache hasil dihapus. Contoh:

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

Contoh query di atas tidak menyebabkan hasilnya di-cache. Anda dapat menyertakan `enableResultCache` (atau`enableResultCacheWithTTL`) dalam kueri yang sama jika Anda ingin menyimpan hasil baru setelah benar-benar menghapus cache yang ada:

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

## Petunjuk kueri Gremlin `numResultsCached`
<a name="gremlin-query-hints-results-cache-numResultsCached"></a>

Petunjuk `numResultsCached` kueri hanya dapat digunakan dengan kueri yang berisi`iterate()`, dan menentukan jumlah maksimum hasil untuk cache untuk kueri yang dilampirkan. Perhatikan bahwa hasil yang di-cache saat `numResultsCached` ada tidak dikembalikan, hanya di-cache.

Misalnya, kueri berikut menetapkan bahwa hingga 100 hasilnya harus di-cache, tetapi tidak ada hasil cache yang dikembalikan:

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

Anda kemudian dapat menggunakan kueri seperti berikut ini untuk mengambil rentang hasil cache (di sini, sepuluh pertama):

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

## Petunjuk kueri Gremlin `noCacheExceptions`
<a name="gremlin-query-hints-results-cache-noCacheExceptions"></a>

Petunjuk `noCacheExceptions` kueri dapat mengambil `false` nilai `true` atau. `true`Nilai menyebabkan pengecualian apa pun yang terkait dengan cache hasil ditekan. Contoh:

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

Secara khusus, ini menekan`QueryLimitExceededException`, yang dinaikkan jika hasil kueri terlalu besar untuk dimasukkan ke dalam cache hasil.

# API status kueri Gremlin
<a name="gremlin-api-status"></a>

Untuk mendapatkan status kueri Gremlin, gunakan HTTP `GET` atau `POST` untuk membuat permintaan ke titik akhir `https://your-neptune-endpoint:port/gremlin/status`. 

## Parameter permintaan status kueri Gremlin
<a name="gremlin-api-status-get-request"></a>
+ **queryId** (*opsional*) - ID dari kueri Gremlin yang berjalan. Hanya menampilkan status kueri yang ditentukan.
+ **includeWaiting** (*opsional*) - Mengembalikan status semua kueri yang menunggu.

  Biasanya, hanya menjalankan kueri yang disertakan dalam respons, tetapi ketika parameter `includeWaiting` ditentukan, status semua kueri yang menunggu juga dikembalikan.

## Sintaks respons status kueri 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"
    }
  ]
}
```

## Nilai respons status kueri Gremlin
<a name="gremlin-api-status-get-response-values"></a>
+ **acceptedQueryCount**— Jumlah kueri yang telah diterima tetapi belum selesai, termasuk kueri dalam antrian.
+ **runningQueryCount**— Jumlah kueri Gremlin yang sedang berjalan.
+ **queries** — Daftar kueri Gremlin saat ini.
+ **queryId** — id GUID untuk kueri. Neptune secara otomatis memberikan nilai ID ini ke setiap kueri, atau Anda juga dapat menetapkan ID Anda sendiri (lihat [Menyuntikkan ID Kustom Ke Dalam Gremlin Neptune atau Kueri SPARQL](features-query-id.md)).
+ **queryEvalStats**— Statistik untuk kueri ini.
+ **subqueries** — Jumlah subqueries dalam kueri ini.
+ **elapsed** — Jumlah milidetik kueri telah berjalan sejauh ini.
+ **cancelled** — True menunjukkan bahwa kueri dibatalkan.
+ **queryString** — Query yang dikirimkan. Ini dipotong menjadi 1024 karakter jika lebih panjang dari itu.
+ **menunggu** - Menunjukkan berapa lama kueri menunggu, dalam milidetik.

## Contoh status kueri Gremlin
<a name="gremlin-api-status-get-example"></a>

Berikut ini adalah contoh perintah status menggunakan `curl` dan `GET` HTTP.

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

Output ini menunjukkan satu kueri yang berjalan.

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

# Pembatalan kueri Gremlin
<a name="gremlin-api-status-cancel"></a>

Untuk mendapatkan status kueri Gremlin, gunakan HTTP `GET` atau `POST` untuk membuat permintaan ke titik akhir `https://your-neptune-endpoint:port/gremlin/status`.

## Parameter permintaan pembatalan kueri Gremlin
<a name="gremlin-api-status-cancel-request"></a>
+ **cancelQuery** — Diperlukan untuk pembatalan. Parameter ini tidak memiliki nilai yang sesuai.
+ **queryId** — ID dari kueri Gremlin yang sedang berjalan untuk dibatalkan.

## Contoh pembatalan kueri Gremlin
<a name="gremlin-api-status-cancel-example"></a>

Berikut ini adalah contoh perintah `curl` untuk membatalkan kueri.

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

Keberhasilan pembatalan kembali HTTP `200` OK.

# Support untuk sesi berbasis skrip Gremlin
<a name="access-graph-gremlin-sessions"></a>

Anda dapat menggunakan sesi Gremlin dengan transaksi implisit di Amazon Neptune. Untuk informasi tentang sesi Gremlin, lihat [Mempertimbangkan Sesi](http://tinkerpop.apache.org/docs/current/reference/#sessions) dalam dokumentasi TinkerPop Apache. Bagian di bawah ini menjelaskan cara menggunakan sesi Gremlin dengan Java.

**penting**  
Saat ini, waktu terlama Neptunus dapat menjaga sesi berbasis skrip terbuka adalah 10 menit. Jika Anda tidak menutup sesi sebelum itu, waktu sesi habis dan semua yang ada di dalamnya di-rollback.

**Topics**
+ [Sesi Gremlin pada konsol Gremlin](#access-graph-gremlin-sessions-console)
+ [Sesi Gremlin dalam Varian Bahasa Gremlin](#access-graph-gremlin-sessions-glv)

## Sesi Gremlin pada konsol Gremlin
<a name="access-graph-gremlin-sessions-console"></a>

Jika Anda membuat koneksi jauh pada Konsol Gremlin tanpa parameter `session`, koneksi jauh dibuat di mode *sessionless*. Dalam mode ini, setiap permintaan yang diserahkan ke server diperlakukan sebagai transaksi lengkap dalam permintaan itu sendiri, dan tidak ada status yang disimpan antara permintaan. Jika permintaan gagal, hanya permintaan tersebut yang di-rollback.

Jika Anda membuat koneksi jarak jauh *yang* menggunakan `session` parameter, Anda membuat sesi berbasis skrip yang berlangsung hingga Anda menutup koneksi jarak jauh. Setiap sesi diidentifikasi oleh UUID unik yang dihasilkan konsol dan dikembalikan kepada Anda.

Berikut ini adalah contoh satu panggilan konsol yang menciptakan sesi. Setelah kueri dikirimkan, panggilan lain menutup sesi dan melakukan kueri.

**catatan**  
Klien Gremlin harus selalu ditutup untuk melepaskan sumber daya sisi server.

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

Untuk informasi dan contoh selengkapnya, lihat [Sesi](http://tinkerpop.apache.org/docs/current/reference/#console-sessions) dalam TinkerPop dokumentasi.

Semua pertanyaan yang Anda jalankan selama sesi membentuk satu transaksi yang tidak dilakukan sampai semua permintaan berhasil dan Anda menutup sambungan jarak jauh. Jika kueri gagal, atau jika Anda tidak menutup koneksi dalam masa sesi maksimum yang Neptune dukung, transaksi sesi tidak dilakukan, dan semua kueri di dalamnya di-rollback.

## Sesi Gremlin dalam Varian Bahasa Gremlin
<a name="access-graph-gremlin-sessions-glv"></a>

Dalam varian bahasa Gremlin (GLV), Anda perlu membuat objek `SessionedClient` untuk mengeluarkan beberapa kueri dalam satu transaksi, seperti dalam contoh berikut.

```
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();
}
```

Baris 3 pada contoh sebelumnya membuat `SessionedClient` objek sesuai dengan opsi konfigurasi yang ditetapkan untuk cluster yang dimaksud. *sessionName*String yang Anda berikan ke metode connect menjadi nama unik sesi. Untuk menghindari tabrakan, gunakan UUID untuk nama tersebut.

Klien mulai transaksi sesi ketika diinisialisasi. Semua kueri yang Anda jalankan selama bentuk sesi dilakukan hanya ketika Anda memanggil `client.close( )`. Sekali lagi, jika kueri gagal, atau jika Anda tidak menutup koneksi dalam masa sesi maksimum yang Neptune dukung, transaksi sesi gagal, dan semua kueri di dalamnya di-rollback.

**catatan**  
Klien Gremlin harus selalu ditutup untuk melepaskan sumber daya sisi server.

```
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();
    }
}
```

# Transaksi Gremlin di Neptunus
<a name="access-graph-gremlin-transactions"></a>

[Ada beberapa konteks di mana transaksi Gremlin dijalankan.](transactions.md) Saat bekerja dengan Gremlin, penting untuk memahami konteks tempat Anda bekerja dan apa implikasinya:
+ **`Script-based`**— Permintaan dibuat menggunakan string Gremlin berbasis teks, seperti ini:
  + Menggunakan driver Java dan `Client.submit(string)`
  + Menggunakan konsol Gremlin dan. `:remote connect`
  + Menggunakan HTTP API.
+ **`Bytecode-based`**— Permintaan dibuat menggunakan bytecode Gremlin serial khas Gremlin Language Variants ([GLV](https://tinkerpop.apache.org/docs/current/reference/#gremlin-drivers-variants)).

  Misalnya, menggunakan driver Java,`g = traversal().withRemote(...)`.

Untuk salah satu konteks di atas, ada konteks tambahan dari permintaan yang dikirim sebagai tanpa sesi atau terikat pada sesi.

**catatan**  
 Transaksi Gremlin harus selalu dilakukan atau dibatalkan, sehingga sumber daya sisi server dapat dilepaskan. Jika terjadi kesalahan selama transaksi, penting untuk mencoba kembali seluruh transaksi dan bukan hanya permintaan tertentu yang gagal. 

## Permintaan tanpa sesi
<a name="access-graph-gremlin-transactions-sessionless"></a>

 Ketika sessionless, permintaan setara dengan satu transaksi.

Untuk skrip, implikasinya adalah bahwa satu atau lebih pernyataan Gremlin yang dikirim dalam satu permintaan akan melakukan atau mengembalikan sebagai satu transaksi. Contoh:

```
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();
```

Untuk bytecode, permintaan tanpa sesi dibuat untuk setiap traversal yang muncul dan dieksekusi dari: `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();
```

## Permintaan terikat pada sesi
<a name="access-graph-gremlin-transactions-session-bound"></a>

Ketika terikat ke sesi, beberapa permintaan dapat diterapkan dalam konteks satu transaksi.

Untuk skrip, implikasinya adalah bahwa tidak perlu menggabungkan semua operasi grafik menjadi satu nilai string yang disematkan:

```
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();
}
```

Untuk bytecode, setelah TinkerPop `3.5.x`, transaksi dapat dikontrol secara eksplisit dan sesi dikelola secara transparan. Gremlin Language Variants (GLV) mendukung `tx()` sintaks Gremlin atau transaksi sebagai berikut: `commit()` `rollback()`

```
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();
    }
}
```

Meskipun contoh di atas ditulis dalam Java, Anda juga dapat menggunakan `tx()` sintaks ini dalam Python, Javascript dan .NET.

**Awas**  
[Kueri hanya-baca tanpa sesi dijalankan di bawah isolasi [SNAPSHOT](transactions-isolation-levels.md), tetapi kueri hanya-baca yang dijalankan dalam transaksi eksplisit dijalankan di bawah isolasi SERIALIZABLE.](transactions-isolation-levels.md) Kueri hanya-baca yang dijalankan di bawah `SERIALIZABLE` isolasi menimbulkan overhead yang lebih tinggi dan dapat memblokir atau diblokir oleh penulisan bersamaan, tidak seperti yang dijalankan di bawah isolasi. `SNAPSHOT`

# Menggunakan API Gremlin dengan Amazon Neptune
<a name="gremlin-api-reference"></a>

**catatan**  
Amazon Neptune tidak mendukung properti `bindings`.

Permintaan Gremlin HTTPS semua menggunakan titik akhir tunggal: `https://your-neptune-endpoint:port/gremlin`. Semua koneksi Neptune harus menggunakan HTTPS.

Anda dapat menghubungkan Konsol Gremlin ke grafik Neptunus secara langsung. WebSockets

Untuk informasi selengkapnya tentang menghubungkan ke titik akhir Gremlin, lihat [Mengakses grafik Neptune dengan Gremlin](access-graph-gremlin.md).

Implementasi Amazon Neptune untuk Gremlin memiliki detail dan perbedaan spesifik yang perlu Anda pertimbangkan. Untuk informasi selengkapnya, lihat [Kepatuhan standar Gremlin di Amazon Neptune](access-graph-gremlin-differences.md).

Untuk informasi tentang bahasa Gremlin dan traversal, lihat [The Traversal](https://tinkerpop.apache.org/docs/current/reference/#traversal) dalam dokumentasi Apache. TinkerPop 

# Hasil kueri cache di Amazon Neptunus Gremlin
<a name="gremlin-results-cache"></a>

Amazon Neptunus mendukung cache hasil untuk kueri Gremlin.

Anda dapat mengaktifkan cache hasil kueri dan kemudian menggunakan petunjuk kueri untuk menyimpan hasil kueri hanya-baca Gremlin.

Setiap menjalankan ulang kueri kemudian mengambil hasil yang di-cache dengan latensi rendah dan tanpa I/O biaya, selama masih dalam cache. Ini berfungsi untuk kueri yang dikirimkan baik pada titik akhir HTTP dan menggunakan Websockets, baik sebagai kode byte atau dalam bentuk string.

**catatan**  
Kueri yang dikirim ke titik akhir profil tidak di-cache bahkan ketika cache kueri diaktifkan.

Anda dapat mengontrol bagaimana cache hasil kueri Neptunus berperilaku dalam beberapa cara. Contoh:
+ Anda bisa mendapatkan hasil cache paginasi, dalam blok.
+ Anda dapat menentukan time-to-live (TTL) untuk kueri tertentu.
+ Anda dapat menghapus cache untuk kueri tertentu.
+ Anda dapat menghapus seluruh cache.
+ Anda dapat mengatur untuk diberi tahu jika hasil melebihi ukuran cache.

Cache dipertahankan menggunakan kebijakan least-recently-used (LRU), yang berarti bahwa setelah ruang yang dialokasikan ke cache penuh, least-recently-used hasilnya dihapus untuk memberi ruang ketika hasil baru di-cache.

**penting**  
Cache hasil kueri tidak tersedia pada `t3.medium` atau jenis `t4.medium` instance.

## Mengaktifkan cache hasil kueri di Neptunus
<a name="gremlin-results-cache-enabling"></a>

 Cache hasil kueri dapat diaktifkan di semua instance dalam cluster atau per-instance. Untuk mengaktifkan cache hasil pada semua instance dalam sebuah cluster, atur `neptune_result_cache` parameter di cluster `cluster-parameter-group` ke`1`. Untuk mengaktifkan ini pada instance tertentu, atur `neptune_result_cache` parameter dalam instance `instance-parameter-group` ke`1`. Pengaturan grup parameter cluster akan mengganti nilai grup parameter instance. 

 Restart diperlukan pada setiap instance yang terpengaruh untuk pengaturan parameter cache hasil yang akan diterapkan. Meskipun Anda dapat mengaktifkan cache hasil di semua instance dalam cluster melalui`cluster-parameter-group`, setiap instance mempertahankan cache-nya sendiri. Fitur cache hasil kueri bukan cache di seluruh cluster. 

Setelah cache hasil diaktifkan, Neptunus menyisihkan sebagian memori saat ini untuk hasil kueri caching. Semakin besar jenis instans yang Anda gunakan dan semakin banyak memori yang tersedia, semakin banyak memori yang disisihkan Neptunus untuk cache.

Jika memori cache hasil terisi, Neptunus secara otomatis least-recently-used menjatuhkan (LRU) hasil cache untuk memberi jalan bagi yang baru.

Anda dapat memeriksa status cache hasil saat ini menggunakan [Status instans](access-graph-status.md) perintah.

## Menggunakan petunjuk untuk menyimpan hasil kueri cache
<a name="gremlin-results-cache-using"></a>

Setelah cache hasil kueri diaktifkan, Anda menggunakan petunjuk kueri untuk mengontrol cache kueri. Semua contoh di bawah ini berlaku untuk traversal kueri yang sama, yaitu:

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

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

Dengan cache hasil kueri diaktifkan, Anda dapat menyimpan hasil kueri Gremlin menggunakan petunjuk `enableResultCache` kueri, sebagai berikut:

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

Neptunus kemudian mengembalikan hasil kueri kepada Anda, dan juga menyimpannya dalam cache. Kemudian, Anda dapat mengakses hasil cache dengan mengeluarkan kueri yang persis sama lagi:

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

Kunci cache yang mengidentifikasi hasil cache adalah string kueri itu sendiri, yaitu:

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

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

Anda dapat menentukan berapa lama hasil kueri harus di-cache dengan menggunakan petunjuk `enableResultCacheWithTTL` kueri. Misalnya, kueri berikut menentukan bahwa hasil kueri akan kedaluwarsa setelah 120 detik:

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

Sekali lagi, kunci cache yang mengidentifikasi hasil cache adalah string kueri dasar:

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

Dan lagi, Anda dapat mengakses hasil cache menggunakan string kueri itu dengan petunjuk `enableResultCache` kueri:

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

Jika 120 detik atau lebih telah berlalu sejak hasilnya di-cache, kueri itu akan mengembalikan hasil baru, dan menyimpannya dalam cache, tanpa ada time-to-live.

Anda juga dapat mengakses hasil cache dengan mengeluarkan kueri yang sama lagi dengan petunjuk `enableResultCacheWithTTL` kueri. Contoh:

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

Hingga 120 detik telah berlalu (yaitu, TTL saat ini berlaku), kueri baru ini menggunakan petunjuk `enableResultCacheWithTTL` kueri mengembalikan hasil yang di-cache. Setelah 120 detik, itu akan mengembalikan hasil baru dan menyimpannya dalam cache dengan time-to-live 140 detik.

**catatan**  
Jika hasil untuk kunci kueri sudah di-cache, maka kunci kueri yang sama dengan `enableResultCacheWithTTL` tidak menghasilkan hasil baru dan tidak berpengaruh pada hasil yang time-to-live saat ini di-cache.  
Jika hasil sebelumnya di-cache menggunakan`enableResultCache`, cache harus dibersihkan terlebih dahulu sebelum `enableResultCacheWithTTL` menghasilkan hasil baru dan menyimpannya untuk TTL yang ditentukannya.
Jika hasil sebelumnya di-cache menggunakan`enableResultCachewithTTL`, TTL sebelumnya harus kedaluwarsa terlebih dahulu sebelum `enableResultCacheWithTTL` menghasilkan hasil baru dan menyimpannya untuk TTL yang ditentukannya.

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

Anda dapat menggunakan petunjuk `invalidateResultCacheKey` kueri untuk menghapus hasil cache untuk satu kueri tertentu. Contoh:

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

Kueri itu menghapus cache untuk kunci kueri`g.V().has('genre','drama').in('likes')`, dan mengembalikan hasil baru untuk kueri itu.

Anda juga dapat menggabungkan `invalidateResultCacheKey` dengan `enableResultCache` atau`enableResultCacheWithTTL`. Misalnya, kueri berikut menghapus hasil cache saat ini, menyimpan hasil baru, dan mengembalikannya:

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

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

Anda dapat menggunakan petunjuk `invalidateResultCache` kueri untuk menghapus semua hasil cache di cache hasil kueri. Contoh:

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

Kueri itu menghapus seluruh cache hasil dan mengembalikan hasil baru untuk kueri.

Anda juga dapat menggabungkan `invalidateResultCache` dengan `enableResultCache` atau`enableResultCacheWithTTL`. Misalnya, kueri berikut menghapus seluruh cache hasil, menyimpan hasil baru untuk kueri ini, dan mengembalikannya:

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

## Paginasi hasil kueri yang di-cache
<a name="gremlin-results-cache-paginating"></a>

Misalkan Anda telah melakukan cache sejumlah besar hasil seperti ini:

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

Sekarang misalkan Anda mengeluarkan kueri rentang berikut:

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

Neptunus pertama kali mencari kunci cache penuh, yaitu. `g.V().has('genre','drama').in('likes').range(0,10)` Jika kunci itu tidak ada, Neptunus selanjutnya melihat apakah ada kunci untuk string kueri itu tanpa rentang (yaitu). `g.V().has('genre','drama').in('likes')` Ketika menemukan kunci itu, Neptunus kemudian mengambil sepuluh hasil pertama dari cache-nya, seperti yang ditentukan oleh rentang.

**catatan**  
Jika Anda menggunakan petunjuk `invalidateResultCacheKey` kueri dengan kueri yang memiliki rentang di akhir, Neptunus menghapus cache untuk kueri tanpa rentang jika tidak menemukan kecocokan yang tepat untuk kueri dengan rentang tersebut.

### Menggunakan `numResultsCached` dengan `.iterate()`
<a name="gremlin-results-cache-paginating-numResultsCached"></a>

Dengan menggunakan petunjuk `numResultsCached` kueri, Anda dapat mengisi cache hasil tanpa mengembalikan semua hasil yang di-cache, yang dapat berguna saat Anda memilih untuk membuat halaman sejumlah besar hasil.

Petunjuk `numResultsCached` kueri hanya berfungsi dengan kueri yang diakhiri dengan. `iterate()`

Misalnya, jika Anda ingin menyimpan 50 hasil pertama dari kueri sampel:

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

Dalam hal ini kunci kueri dalam cache adalah:`g.with("Neptune#numResultsCached", 50).V().has('genre','drama').in('likes')`. Anda sekarang dapat mengambil sepuluh pertama dari hasil cache dengan kueri ini:

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

Dan, Anda dapat mengambil sepuluh hasil berikutnya dari kueri sebagai berikut:

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

Jangan lupa sertakan `numResultsCached` petunjuknya\$1 Ini adalah bagian penting dari kunci kueri dan karena itu harus ada untuk mengakses hasil cache.

**Beberapa hal yang perlu diingat saat menggunakan `numResultsCached`**
+ **Nomor yang Anda berikan `numResultsCached` diterapkan di akhir kueri.**   Ini berarti, misalnya, bahwa kueri berikut sebenarnya cache menghasilkan rentang`(1000, 1500)`:

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 500)
   .V().range(1000, 2000).iterate()
  ```
+ **Nomor yang Anda berikan `numResultsCached` menentukan jumlah maksimum hasil untuk cache.**   Ini berarti, misalnya, bahwa kueri berikut sebenarnya cache menghasilkan rentang`(1000, 2000)`:

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 100000)
   .V().range(1000, 2000).iterate()
  ```
+ **Hasil yang di-cache oleh kueri yang diakhiri dengan `.range().iterate()` memiliki jangkauannya sendiri.**   Misalnya, Anda menyimpan hasil cache menggunakan kueri seperti ini:

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

  Untuk mengambil 100 hasil pertama dari cache, Anda akan menulis kueri seperti ini:

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

  Seratus hasil itu akan setara dengan hasil dari kueri dasar dalam kisaran tersebut`(1000, 1100)`.

## Kunci cache kueri yang digunakan untuk menemukan hasil cache
<a name="gremlin-results-cache-query-keys"></a>

Setelah hasil kueri di-cache, kueri berikutnya dengan *kunci cache kueri* yang sama mengambil hasil dari cache daripada menghasilkan yang baru. Kunci cache kueri dari kueri dievaluasi sebagai berikut:

1. Semua petunjuk kueri terkait cache diabaikan, kecuali untuk. `numResultsCached`

1. `iterate()`Langkah terakhir diabaikan.

1. Sisa kueri diurutkan sesuai dengan representasi kode byte.

String yang dihasilkan dicocokkan dengan indeks hasil kueri yang sudah ada di cache untuk menentukan apakah ada cache hit untuk kueri.

Misalnya, ambil kueri ini:

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

Ini akan disimpan sebagai versi byte-code ini:

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

## Pengecualian terkait dengan cache hasil
<a name="gremlin-results-cache-exceptions"></a>

Jika hasil kueri yang Anda coba cache terlalu besar untuk dimasukkan ke dalam memori cache bahkan setelah menghapus semua yang sebelumnya di-cache, Neptunus menimbulkan kesalahan. `QueryLimitExceededException` Tidak ada hasil yang dikembalikan, dan pengecualian menghasilkan pesan galat berikut:

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

Anda dapat menekan pesan ini menggunakan petunjuk `noCacheExceptions` kueri, sebagai berikut:

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

# Membuat peningkatan yang efisien dengan `mergeV()` Gremlin dan langkah-langkah `mergeE()`
<a name="gremlin-efficient-upserts"></a>

Upsert (atau sisipan bersyarat) menggunakan kembali simpul atau tepi jika sudah ada, atau membuatnya jika tidak. Upserts yang efisien dapat membuat perbedaan yang signifikan dalam kinerja kueri Gremlin.

Upserts memungkinkan Anda untuk menulis operasi penyisipan idempoten: tidak peduli berapa kali Anda menjalankan operasi seperti itu, hasil keseluruhannya sama. Ini berguna dalam skenario penulisan yang sangat bersamaan di mana modifikasi bersamaan pada bagian grafik yang sama dapat memaksa satu atau lebih transaksi untuk memutar kembali dengan a`ConcurrentModificationException`, sehingga memerlukan percobaan ulang.

Misalnya, kueri berikut meningkatkan simpul dengan menggunakan yang disediakan `Map` untuk pertama kali mencoba menemukan simpul dengan a of. `T.id` `"v-1"` Jika simpul itu ditemukan maka dikembalikan. Jika tidak ditemukan maka simpul dengan itu `id` dan properti dibuat melalui `onCreate` klausa.

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

## Batching upserts untuk meningkatkan throughput
<a name="gremlin-upserts-batching"></a>

Untuk skenario penulisan throughput tinggi, Anda dapat berantai `mergeV()` dan `mergeE()` melangkah bersama untuk meningkatkan simpul dan tepi dalam batch. Batching mengurangi overhead transaksional untuk menaikkan sejumlah besar simpul dan tepi. Anda kemudian dapat lebih meningkatkan throughput dengan meningkatkan permintaan batch secara paralel menggunakan beberapa klien.

Sebagai aturan praktis, kami merekomendasikan untuk meningkatkan sekitar 200 catatan per permintaan batch. Rekaman adalah satu titik atau label tepi atau properti. Sebuah simpul dengan label tunggal dan 4 properti, misalnya, membuat 5 catatan. Tepi dengan label dan properti tunggal menciptakan 2 catatan. Jika Anda ingin meningkatkan kumpulan simpul, masing-masing dengan label tunggal dan 4 properti, Anda harus mulai dengan ukuran batch 40, karena. `200 / (1 + 4) = 40`

Anda dapat bereksperimen dengan ukuran batch. 200 catatan per batch adalah titik awal yang baik, tetapi ukuran batch yang ideal mungkin lebih tinggi atau lebih rendah tergantung pada beban kerja Anda. Perhatikan, bagaimanapun, bahwa Neptunus dapat membatasi jumlah keseluruhan langkah Gremlin per permintaan. Batas ini tidak didokumentasikan, tetapi untuk berada di sisi yang aman, cobalah untuk memastikan bahwa permintaan Anda mengandung tidak lebih dari 1.500 langkah Gremlin. Neptunus dapat menolak permintaan batch besar dengan lebih dari 1.500 langkah.

Untuk meningkatkan throughput, Anda dapat meningkatkan batch secara paralel menggunakan beberapa klien (lihat). [Membuat Penulisan Gremlin Multithreaded yang Efisien](best-practices-gremlin-multithreaded-writes.md) Jumlah klien harus sama dengan jumlah thread pekerja pada instance penulis Neptunus Anda, yang biasanya 2 x jumlah CPUs v di server. Misalnya, sebuah `r5.8xlarge` instance memiliki 32 v CPUs dan 64 thread pekerja. Untuk skenario penulisan throughput tinggi menggunakan`r5.8xlarge`, Anda akan menggunakan 64 klien yang menulis batch upserts ke Neptunus secara paralel.

Setiap klien harus mengirimkan permintaan batch dan menunggu permintaan selesai sebelum mengirimkan permintaan lain. Meskipun beberapa klien berjalan secara paralel, setiap klien individu mengirimkan permintaan secara serial. Ini memastikan bahwa server disuplai dengan aliran permintaan yang stabil yang menempati semua thread pekerja tanpa membanjiri antrian permintaan sisi server (lihat). [Mengukur instans DB dalam sebuah klaster Neptune DB](feature-overview-db-clusters.md#feature-overview-sizing-instances)

## Cobalah untuk menghindari langkah-langkah yang menghasilkan banyak pelintas
<a name="gremlin-upserts-single-traverser"></a>

Ketika langkah Gremlin dijalankan, dibutuhkan traverser masuk, dan memancarkan satu atau lebih traverser keluaran. Jumlah pelintas yang dipancarkan oleh satu langkah menentukan berapa kali langkah berikutnya dijalankan.

Biasanya, ketika melakukan operasi batch Anda ingin setiap operasi, seperti upsert vertex A, untuk mengeksekusi sekali, sehingga urutan operasi terlihat seperti ini: upsert vertex A, kemudian upsert vertex B, kemudian upsert vertex C, dan seterusnya. Selama sebuah langkah membuat atau memodifikasi hanya satu elemen, ia hanya memancarkan satu traverser, dan langkah-langkah yang mewakili operasi berikutnya dijalankan hanya sekali. Jika, di sisi lain, sebuah operasi membuat atau memodifikasi lebih dari satu elemen, ia memancarkan beberapa pelintas, yang pada gilirannya menyebabkan langkah-langkah selanjutnya dieksekusi beberapa kali, sekali per traverser yang dipancarkan. Hal ini dapat mengakibatkan database melakukan pekerjaan tambahan yang tidak perlu, dan dalam beberapa kasus dapat mengakibatkan penciptaan simpul tambahan yang tidak diinginkan, tepi atau nilai properti.

Contoh bagaimana hal-hal bisa salah adalah dengan kueri seperti`g.V().addV()`. Kueri sederhana ini menambahkan simpul untuk setiap simpul yang ditemukan dalam grafik, karena `V()` memancarkan traverser untuk setiap simpul dalam grafik dan masing-masing pelintas tersebut memicu panggilan ke. `addV()`

Lihat [Mencampur upserts dan sisipan](#gremlin-upserts-and-inserts) cara menangani operasi yang dapat memancarkan banyak pelintas.

## Menaikkan simpul
<a name="gremlin-upserts-vertices"></a>

`mergeV()`Langkah ini dirancang khusus untuk menaikkan simpul. Dibutuhkan sebagai argumen a `Map` yang mewakili elemen untuk mencocokkan simpul yang ada dalam grafik, dan jika elemen tidak ditemukan, menggunakannya `Map` untuk membuat simpul baru. Langkah ini juga memungkinkan Anda untuk mengubah perilaku jika terjadi penciptaan atau kecocokan, di mana `option()` modulator dapat diterapkan dengan `Merge.onCreate` dan `Merge.onMatch` token untuk mengontrol perilaku masing-masing. Lihat [Dokumentasi TinkerPop Referensi](https://tinkerpop.apache.org/docs/current/reference/#mergevertex-step) untuk informasi lebih lanjut tentang cara menggunakan langkah ini.

Anda dapat menggunakan ID simpul untuk menentukan apakah ada simpul tertentu. Ini adalah pendekatan yang lebih disukai, karena Neptunus mengoptimalkan upserts untuk kasus penggunaan yang sangat bersamaan. IDs Sebagai contoh, kueri berikut membuat simpul dengan ID simpul yang diberikan jika belum ada, atau menggunakannya kembali jika memang demikian:

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

Perhatikan bahwa kueri ini diakhiri dengan `id()` langkah. Meskipun tidak sepenuhnya diperlukan untuk tujuan meningkatkan simpul, `id()` langkah ke akhir kueri upsert memastikan bahwa server tidak membuat serial semua properti simpul kembali ke klien, yang membantu mengurangi biaya penguncian kueri.

Atau, Anda dapat menggunakan properti simpul untuk mengidentifikasi simpul:

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

Jika memungkinkan, gunakan sendiri yang disediakan pengguna IDs untuk membuat simpul, dan gunakan ini IDs untuk menentukan apakah simpul ada selama operasi upsert. Ini memungkinkan Neptunus mengoptimalkan upserts. Upsert berbasis ID dapat secara signifikan lebih efisien daripada upsert berbasis properti ketika modifikasi bersamaan adalah umum.

### Bagian atas simpul berantai
<a name="gremlin-upserts-vertices-chaining"></a>

Anda dapat menghubungkan bagian atas simpul bersama-sama untuk menyisipkannya dalam batch:

```
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()
```

Atau, Anda juga dapat menggunakan `mergeV()` sintaks ini:

```
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'])
```

Namun, karena bentuk kueri ini menyertakan elemen dalam kriteria penelusuran yang berlebihan untuk pencarian dasar`id`, itu tidak seefisien kueri sebelumnya.

## Tepi yang menjulang
<a name="gremlin-upserts-edges"></a>

`mergeE()`Langkah ini dirancang khusus untuk menaikkan tepi. Dibutuhkan `Map` sebagai argumen yang mewakili elemen untuk mencocokkan tepi yang ada dalam grafik dan jika elemen tidak ditemukan, menggunakannya `Map` untuk membuat tepi baru. Langkah ini juga memungkinkan Anda untuk mengubah perilaku jika terjadi penciptaan atau kecocokan, di mana `option()` modulator dapat diterapkan dengan `Merge.onCreate` dan `Merge.onMatch` token untuk mengontrol perilaku masing-masing. Lihat [Dokumentasi TinkerPop Referensi](https://tinkerpop.apache.org/docs/current/reference/#mergeedge-step) untuk informasi lebih lanjut tentang cara menggunakan langkah ini.

Anda dapat menggunakan tepi IDs untuk menaikkan tepi dengan cara yang sama Anda menaikkan simpul menggunakan simpul kustom. IDs Sekali lagi, ini adalah pendekatan yang disukai karena memungkinkan Neptunus untuk mengoptimalkan kueri. Misalnya, kueri berikut membuat tepi berdasarkan ID tepinya jika belum ada, atau menggunakannya kembali jika ada. Kueri juga menggunakan simpul `Direction.from` dan `Direction.to` simpul jika perlu membuat tepi baru: IDs 

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

Perhatikan bahwa kueri ini diakhiri dengan `id()` langkah. Meskipun tidak sepenuhnya diperlukan untuk tujuan meningkatkan tepi, menambahkan `id()` langkah ke akhir kueri upsert memastikan bahwa server tidak membuat serial semua properti edge kembali ke klien, yang membantu mengurangi biaya penguncian kueri.

Banyak aplikasi menggunakan simpul khusus IDs, tetapi meninggalkan Neptunus untuk menghasilkan tepi. IDs Jika Anda tidak tahu ID tepi, tetapi Anda tahu `from` dan `to` simpulnya IDs, Anda dapat menggunakan kueri semacam ini untuk meningkatkan tepi:

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

Semua simpul yang direferensikan oleh `mergeE()` harus ada untuk langkah untuk membuat tepi.

### Bagian atas tepi rantai
<a name="gremlin-upserts-edges-chaining"></a>

Seperti halnya vertex upserts, sangat mudah untuk menggabungkan `mergeE()` langkah-langkah bersama untuk permintaan batch:

```
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()
```

## Menggabungkan vertex dan edge upserts
<a name="gremlin-upserts-vertexes-and-edges"></a>

Terkadang Anda mungkin ingin meningkatkan kedua simpul dan tepi yang menghubungkannya. Anda dapat mencampur contoh batch yang disajikan di sini. Contoh berikut meningkatkan 3 simpul dan 2 tepi:

```
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()
```

## Mencampur upserts dan sisipan
<a name="gremlin-upserts-and-inserts"></a>

Terkadang Anda mungkin ingin meningkatkan kedua simpul dan tepi yang menghubungkannya. Anda dapat mencampur contoh batch yang disajikan di sini. Contoh berikut meningkatkan 3 simpul dan 2 tepi:

Upserts biasanya melanjutkan satu elemen pada satu waktu. Jika Anda tetap berpegang pada pola upsert yang disajikan di sini, setiap operasi upsert memancarkan satu traverser, yang menyebabkan operasi berikutnya dijalankan hanya sekali.

Namun, terkadang Anda mungkin ingin mencampur upserts dengan sisipan. Ini bisa terjadi, misalnya, jika Anda menggunakan tepi untuk mewakili contoh tindakan atau peristiwa. Permintaan mungkin menggunakan upserts untuk memastikan bahwa semua simpul yang diperlukan ada, dan kemudian menggunakan sisipan untuk menambahkan tepi. Dengan permintaan semacam ini, perhatikan potensi jumlah pelintas yang dipancarkan dari setiap operasi.

Perhatikan contoh berikut, yang mencampur upsert dan sisipan untuk menambahkan tepi yang mewakili peristiwa ke dalam grafik:

```
// 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()
```

Kueri harus menyisipkan 5 tepi: 2 tepi DIIKUTI dan 3 tepi VISITED. Namun, kueri sebagai tertulis menyisipkan 8 tepi: 2 DIIKUTI dan 6 DIKUNJUNGI. Alasan untuk ini adalah bahwa operasi yang menyisipkan 2 tepi FOLLOW memancarkan 2 traversers, menyebabkan operasi penyisipan berikutnya, yang menyisipkan 3 tepi, dieksekusi dua kali.

Perbaikannya adalah menambahkan `fold()` langkah setelah setiap operasi yang berpotensi memancarkan lebih dari satu traverser:

```
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()
```

Di sini kita telah memasukkan `fold()` langkah setelah operasi yang menyisipkan tepi DIIKUTI. Ini menghasilkan traverser tunggal, yang kemudian menyebabkan operasi berikutnya dieksekusi hanya sekali.

Kelemahan dari pendekatan ini adalah bahwa query sekarang tidak sepenuhnya dioptimalkan, karena tidak `fold()` dioptimalkan. Operasi insert yang mengikuti sekarang juga tidak `fold()` akan dioptimalkan.

Jika Anda perlu menggunakan `fold()` untuk mengurangi jumlah pelintas atas nama langkah-langkah selanjutnya, cobalah untuk memesan operasi Anda sehingga yang paling murah menempati bagian kueri yang tidak dioptimalkan.

## Pengaturan Kardinalitas
<a name="gremlin-upserts-setting-cardinality"></a>

 Kardinalitas default untuk properti simpul di Neptunus diatur, yang berarti bahwa ketika menggunakan mergeV () nilai yang diberikan dalam peta semuanya akan diberikan kardinalitas itu. Untuk menggunakan kardinalitas tunggal, Anda harus eksplisit dalam penggunaannya. Mulai dari TinkerPop 3.7.0, ada sintaks baru yang memungkinkan kardinalitas diberikan sebagai bagian dari peta seperti yang ditunjukkan pada contoh berikut: 

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

 Atau, Anda dapat menetapkan kardinalitas sebagai default untuk itu `option` sebagai berikut: 

```
// 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)
```

 Ada lebih sedikit opsi untuk mengatur kardinalitas `mergeV()` sebelum versi 3.7.0. Pendekatan umum adalah kembali ke `property()` langkah sebagai berikut: 

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

**catatan**  
 Pendekatan ini hanya akan bekerja dengan `mergeV()` ketika digunakan dengan langkah awal. Oleh karena itu Anda tidak akan dapat berantai `mergeV()` dalam satu traversal karena yang pertama `mergeV()` setelah langkah awal yang menggunakan sintaks ini akan menghasilkan kesalahan jika traverser yang masuk menjadi elemen grafik. Dalam hal ini, Anda ingin memecah `mergeV()` panggilan Anda menjadi beberapa permintaan di mana masing-masing dapat menjadi langkah awal. 

# Membuat peningkatan Gremlin yang efisien dengan `fold()/coalesce()/unfold()`
<a name="gremlin-efficient-upserts-pre-3.6"></a>

Upsert (atau sisipan bersyarat) menggunakan kembali simpul atau tepi jika sudah ada, atau membuatnya jika tidak. Upserts yang efisien dapat membuat perbedaan yang signifikan dalam kinerja kueri Gremlin.

Halaman ini menunjukkan bagaimana menggunakan pola `fold()/coalesce()/unfold()` Gremlin untuk membuat upserts yang efisien. Namun, dengan rilis TinkerPop versi 3.6.x yang diperkenalkan di Neptunus dalam versi mesin [1.2.1.0](engine-releases-1.2.1.0.md), langkah baru `mergeV()` dan lebih disukai dalam banyak kasus. `mergeE()` `fold()/coalesce()/unfold()`Pola yang dijelaskan di sini mungkin masih berguna dalam beberapa situasi yang kompleks, tetapi dalam penggunaan umum `mergeV()` dan `mergeE()` jika Anda bisa, seperti yang dijelaskan dalam[Membuat peningkatan yang efisien dengan `mergeV()` Gremlin dan langkah-langkah `mergeE()`](gremlin-efficient-upserts.md).

Upserts memungkinkan Anda untuk menulis operasi penyisipan idempoten: tidak peduli berapa kali Anda menjalankan operasi seperti itu, hasil keseluruhannya sama. Ini berguna dalam skenario penulisan yang sangat bersamaan di mana modifikasi bersamaan pada bagian grafik yang sama dapat memaksa satu atau lebih transaksi untuk memutar kembali dengan a`ConcurrentModificationException`, sehingga memerlukan percobaan ulang.

Misalnya, kueri berikut meningkatkan simpul dengan terlebih dahulu mencari simpul yang ditentukan dalam kumpulan data, dan kemudian melipat hasilnya ke dalam daftar. Dalam traversal pertama yang diberikan ke `coalesce()` langkah, kueri kemudian membuka daftar ini. Jika daftar yang dibuka tidak kosong, hasilnya dipancarkan dari. `coalesce()` Namun, jika `unfold()` mengembalikan koleksi kosong karena simpul saat ini tidak ada, lanjutkan `coalesce()` untuk mengevaluasi traversal kedua yang telah disediakan, dan dalam traversal kedua ini kueri membuat simpul yang hilang.

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

## Gunakan formulir yang dioptimalkan `coalesce()` untuk upserts
<a name="gremlin-upserts-pre-3.6-coalesce"></a>

Neptunus dapat mengoptimalkan `fold().coalesce(unfold(), ...)` idiom untuk membuat pembaruan throughput tinggi, tetapi pengoptimalan ini hanya berfungsi jika kedua bagian pengembalian baik simpul atau tepi `coalesce()` tetapi tidak ada yang lain. Jika Anda mencoba mengembalikan sesuatu yang berbeda, seperti properti, dari bagian mana pun`coalesce()`, pengoptimalan Neptunus tidak terjadi. Kueri mungkin berhasil, tetapi tidak akan berkinerja sebaik versi yang dioptimalkan, terutama terhadap kumpulan data besar.

Karena kueri upsert yang tidak dioptimalkan meningkatkan waktu eksekusi dan mengurangi throughput, ada baiknya menggunakan `explain` titik akhir Gremlin untuk menentukan apakah kueri upsert sepenuhnya dioptimalkan. Saat meninjau `explain` rencana, cari garis yang dimulai dengan `+ not converted into Neptune steps` dan`WARNING: >>`. Contoh:

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

Peringatan ini dapat membantu Anda mengidentifikasi bagian-bagian kueri yang mencegahnya dioptimalkan sepenuhnya.

Terkadang tidak mungkin untuk mengoptimalkan kueri sepenuhnya. Dalam situasi ini Anda harus mencoba meletakkan langkah-langkah yang tidak dapat dioptimalkan di akhir kueri, sehingga memungkinkan mesin untuk mengoptimalkan sebanyak mungkin langkah. Teknik ini digunakan dalam beberapa contoh batch upsert, di mana semua upsert yang dioptimalkan untuk satu set simpul atau tepi dilakukan sebelum modifikasi tambahan yang berpotensi tidak dioptimalkan diterapkan pada simpul atau tepi yang sama.

## Batching upserts untuk meningkatkan throughput
<a name="gremlin-upserts-pre-3.6-batching"></a>

Untuk skenario penulisan throughput tinggi, Anda dapat menggabungkan langkah-langkah upsert bersama-sama untuk meningkatkan simpul dan tepi dalam batch. Batching mengurangi overhead transaksional untuk menaikkan sejumlah besar simpul dan tepi. Anda kemudian dapat lebih meningkatkan throughput dengan meningkatkan permintaan batch secara paralel menggunakan beberapa klien.

Sebagai aturan praktis, kami merekomendasikan untuk meningkatkan sekitar 200 catatan per permintaan batch. Rekaman adalah satu titik atau label tepi atau properti. Sebuah simpul dengan label tunggal dan 4 properti, misalnya, membuat 5 catatan. Tepi dengan label dan properti tunggal menciptakan 2 catatan. Jika Anda ingin meningkatkan kumpulan simpul, masing-masing dengan label tunggal dan 4 properti, Anda harus mulai dengan ukuran batch 40, karena. `200 / (1 + 4) = 40`

Anda dapat bereksperimen dengan ukuran batch. 200 catatan per batch adalah titik awal yang baik, tetapi ukuran batch yang ideal mungkin lebih tinggi atau lebih rendah tergantung pada beban kerja Anda. Perhatikan, bagaimanapun, bahwa Neptunus dapat membatasi jumlah keseluruhan langkah Gremlin per permintaan. Batas ini tidak didokumentasikan, tetapi untuk berada di sisi yang aman cobalah untuk memastikan bahwa permintaan Anda mengandung tidak lebih dari 1500 langkah Gremlin. Neptunus dapat menolak permintaan batch besar dengan lebih dari 1500 langkah.

Untuk meningkatkan throughput, Anda dapat meningkatkan batch secara paralel menggunakan beberapa klien (lihat). [Membuat Penulisan Gremlin Multithreaded yang Efisien](best-practices-gremlin-multithreaded-writes.md) Jumlah klien harus sama dengan jumlah thread pekerja pada instance penulis Neptunus Anda, yang biasanya 2 x jumlah CPUs v di server. Misalnya, sebuah `r5.8xlarge` instance memiliki 32 v CPUs dan 64 thread pekerja. Untuk skenario penulisan throughput tinggi menggunakan`r5.8xlarge`, Anda akan menggunakan 64 klien yang menulis batch upserts ke Neptunus secara paralel.

Setiap klien harus mengirimkan permintaan batch dan menunggu permintaan selesai sebelum mengirimkan permintaan lain. Meskipun beberapa klien berjalan secara paralel, setiap klien individu mengirimkan permintaan secara serial. Ini memastikan bahwa server disuplai dengan aliran permintaan yang stabil yang menempati semua thread pekerja tanpa membanjiri antrian permintaan sisi server (lihat). [Mengukur instans DB dalam sebuah klaster Neptune DB](feature-overview-db-clusters.md#feature-overview-sizing-instances)

## Cobalah untuk menghindari langkah-langkah yang menghasilkan banyak pelintas
<a name="gremlin-upserts-pre-3.6-single-traverser"></a>

Ketika langkah Gremlin dijalankan, dibutuhkan traverser masuk, dan memancarkan satu atau lebih traverser keluaran. Jumlah pelintas yang dipancarkan oleh satu langkah menentukan berapa kali langkah berikutnya dijalankan.

Biasanya, ketika melakukan operasi batch Anda ingin setiap operasi, seperti upsert vertex A, untuk mengeksekusi sekali, sehingga urutan operasi terlihat seperti ini: upsert vertex A, kemudian upsert vertex B, kemudian upsert vertex C, dan seterusnya. Selama sebuah langkah membuat atau memodifikasi hanya satu elemen, ia hanya memancarkan satu traverser, dan langkah-langkah yang mewakili operasi berikutnya dijalankan hanya sekali. Jika, di sisi lain, sebuah operasi membuat atau memodifikasi lebih dari satu elemen, ia memancarkan beberapa pelintas, yang pada gilirannya menyebabkan langkah-langkah selanjutnya dieksekusi beberapa kali, sekali per traverser yang dipancarkan. Hal ini dapat mengakibatkan database melakukan pekerjaan tambahan yang tidak perlu, dan dalam beberapa kasus dapat mengakibatkan penciptaan simpul tambahan yang tidak diinginkan, tepi atau nilai properti.

Contoh bagaimana hal-hal bisa salah adalah dengan kueri seperti`g.V().addV()`. Kueri sederhana ini menambahkan simpul untuk setiap simpul yang ditemukan dalam grafik, karena `V()` memancarkan traverser untuk setiap simpul dalam grafik dan masing-masing pelintas tersebut memicu panggilan ke. `addV()`

Lihat [Mencampur upserts dan sisipan](#gremlin-upserts-pre-3.6-and-inserts) cara menangani operasi yang dapat memancarkan banyak pelintas.

## Menaikkan simpul
<a name="gremlin-upserts-pre-3.6-vertices"></a>

Anda dapat menggunakan ID simpul untuk menentukan apakah ada simpul yang sesuai. Ini adalah pendekatan yang lebih disukai, karena Neptunus mengoptimalkan upserts untuk kasus penggunaan yang sangat bersamaan. IDs Sebagai contoh, kueri berikut membuat simpul dengan ID simpul yang diberikan jika belum ada, atau menggunakannya kembali jika memang demikian:

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

Perhatikan bahwa kueri ini diakhiri dengan `id()` langkah. Meskipun tidak sepenuhnya diperlukan untuk tujuan meningkatkan simpul, menambahkan `id()` langkah ke akhir kueri upsert memastikan bahwa server tidak membuat serial semua properti simpul kembali ke klien, yang membantu mengurangi biaya penguncian kueri.

Atau, Anda dapat menggunakan properti simpul untuk menentukan apakah simpul itu ada:

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

Jika memungkinkan, gunakan sendiri yang disediakan pengguna IDs untuk membuat simpul, dan gunakan ini IDs untuk menentukan apakah simpul ada selama operasi upsert. Ini memungkinkan Neptunus mengoptimalkan upserts di sekitar. IDs Peningkatan berbasis ID dapat secara signifikan lebih efisien daripada peningkatan berbasis properti dalam skenario modifikasi yang sangat bersamaan.

### Bagian atas simpul berantai
<a name="gremlin-upserts-pre-3.6-vertices-chaining"></a>

Anda dapat menghubungkan bagian atas simpul bersama-sama untuk menyisipkannya dalam batch:

```
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()
```

## Tepi yang menjulang
<a name="gremlin-upserts-pre-3.6-edges"></a>

Anda dapat menggunakan tepi IDs untuk menaikkan tepi dengan cara yang sama Anda menaikkan simpul menggunakan simpul kustom. IDs Sekali lagi, ini adalah pendekatan yang disukai karena memungkinkan Neptunus untuk mengoptimalkan kueri. Misalnya, kueri berikut membuat tepi berdasarkan ID tepinya jika belum ada, atau menggunakannya kembali jika ada. Kueri juga menggunakan simpul `from` dan `to` simpul jika perlu membuat tepi baru. IDs 

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

Banyak aplikasi menggunakan simpul khusus IDs, tetapi meninggalkan Neptunus untuk menghasilkan tepi. IDs Jika Anda tidak tahu ID tepi, tetapi Anda tahu `from` dan `to` simpul IDs, Anda dapat menggunakan formulasi ini untuk meningkatkan tepi:

```
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()
```

Perhatikan bahwa langkah simpul dalam `where()` klausa harus `inV()` (atau `outV()` jika Anda pernah `inE()` menemukan tepi), bukan. `otherV()` Jangan gunakan`otherV()`, di sini, atau kueri tidak akan dioptimalkan dan kinerja akan menurun. Misalnya, Neptunus tidak akan mengoptimalkan kueri berikut:

```
// 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()
```

Jika Anda tidak tahu tepi atau simpul IDs di depan, Anda dapat meningkatkan menggunakan properti simpul:

```
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()
```

Seperti halnya vertex upserts, lebih baik menggunakan edge upserts berbasis ID menggunakan ID tepi atau `from` dan `to` simpul, daripada upsert berbasis properti IDs, sehingga Neptunus dapat sepenuhnya mengoptimalkan upsert.

### Memeriksa `from` dan `to` keberadaan simpul
<a name="gremlin-upserts-pre-3.6-edges-checking"></a>

Perhatikan konstruksi langkah-langkah yang membuat tepi baru:`addE().from().to()`. Konstruksi ini memastikan bahwa kueri memeriksa keberadaan simpul `from` dan `to` simpul. Jika salah satu dari ini tidak ada, kueri mengembalikan kesalahan sebagai berikut:

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

Jika mungkin salah satu `from` atau `to` simpul tidak ada, Anda harus mencoba untuk meningkatkannya sebelum menaikkan tepi di antara keduanya. Lihat [Menggabungkan vertex dan edge upserts](#gremlin-upserts-pre-3.6-vertexes-and-edges).

Ada konstruksi alternatif untuk membuat tepi yang tidak boleh Anda gunakan:`V().addE().to()`. Itu hanya menambahkan tepi jika `from` simpul ada. Jika `to` simpul tidak ada, kueri menghasilkan kesalahan, seperti yang dijelaskan sebelumnya, tetapi jika `from` simpul tidak ada, itu diam-diam gagal memasukkan tepi, tanpa menghasilkan kesalahan apa pun. Misalnya, upsert berikut selesai tanpa menaikkan tepi jika `from` simpul tidak ada:

```
// 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()
```

### Bagian atas tepi rantai
<a name="gremlin-upserts-pre-3.6-edges-chaining"></a>

Jika Anda ingin menghubungkan edge upserts bersama-sama untuk membuat permintaan batch, Anda harus memulai setiap upsert dengan pencarian simpul, bahkan jika Anda sudah tahu tepi. IDs

Jika Anda sudah tahu tepi IDs yang ingin Anda sertakan, dan simpul dan `to` simpul, Anda dapat menggunakan formulasi ini: IDs `from`

```
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()
```

Mungkin skenario peningkatan tepi batch yang paling umum adalah Anda mengetahui `from` dan `to` simpulnya IDs, tetapi tidak tahu tepi IDs yang ingin Anda tingkatkan. Dalam hal ini, gunakan formulasi berikut:

```
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()
```

Jika Anda mengetahui IDs tepi yang ingin Anda sertakan, tetapi tidak tahu simpulnya `from` dan IDs `to` simpulnya (ini tidak biasa), Anda dapat menggunakan formulasi ini:

```
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()
```

## Menggabungkan vertex dan edge upserts
<a name="gremlin-upserts-pre-3.6-vertexes-and-edges"></a>

Terkadang Anda mungkin ingin meningkatkan kedua simpul dan tepi yang menghubungkannya. Anda dapat mencampur contoh batch yang disajikan di sini. Contoh berikut meningkatkan 3 simpul dan 2 tepi:

```
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()
```

## Mencampur upserts dan sisipan
<a name="gremlin-upserts-pre-3.6-and-inserts"></a>

Terkadang Anda mungkin ingin meningkatkan kedua simpul dan tepi yang menghubungkannya. Anda dapat mencampur contoh batch yang disajikan di sini. Contoh berikut meningkatkan 3 simpul dan 2 tepi:

Upserts biasanya melanjutkan satu elemen pada satu waktu. Jika Anda tetap berpegang pada pola upsert yang disajikan di sini, setiap operasi upsert memancarkan satu traverser, yang menyebabkan operasi berikutnya dijalankan hanya sekali.

Namun, terkadang Anda mungkin ingin mencampur upserts dengan sisipan. Ini bisa terjadi, misalnya, jika Anda menggunakan tepi untuk mewakili contoh tindakan atau peristiwa. Permintaan mungkin menggunakan upserts untuk memastikan bahwa semua simpul yang diperlukan ada, dan kemudian menggunakan sisipan untuk menambahkan tepi. Dengan permintaan semacam ini, perhatikan potensi jumlah pelintas yang dipancarkan dari setiap operasi.

Perhatikan contoh berikut, yang mencampur upsert dan sisipan untuk menambahkan tepi yang mewakili peristiwa ke dalam grafik:

```
// 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()
```

Kueri harus menyisipkan 5 tepi: 2 tepi DIIKUTI dan 3 tepi VISITED. Namun, kueri sebagai tertulis menyisipkan 8 tepi: 2 DIIKUTI dan 6 DIKUNJUNGI. Alasan untuk ini adalah bahwa operasi yang menyisipkan 2 tepi FOLLOW memancarkan 2 traversers, menyebabkan operasi penyisipan berikutnya, yang menyisipkan 3 tepi, dieksekusi dua kali.

Perbaikannya adalah menambahkan `fold()` langkah setelah setiap operasi yang berpotensi memancarkan lebih dari satu traverser:

```
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()
```

Di sini kita telah memasukkan `fold()` langkah setelah operasi yang menyisipkan tepi DIIKUTI. Ini menghasilkan traverser tunggal, yang kemudian menyebabkan operasi berikutnya dieksekusi hanya sekali.

Kelemahan dari pendekatan ini adalah bahwa query sekarang tidak sepenuhnya dioptimalkan, karena tidak `fold()` dioptimalkan. Operasi insert yang mengikuti sekarang tidak `fold()` akan dioptimalkan.

Jika Anda perlu menggunakan `fold()` untuk mengurangi jumlah pelintas atas nama langkah-langkah selanjutnya, cobalah untuk memesan operasi Anda sehingga yang paling murah menempati bagian kueri yang tidak dioptimalkan.

## Upserts yang memodifikasi simpul dan tepi yang ada
<a name="gremlin-upserts-pre-3.6-that-modify"></a>

Terkadang Anda ingin membuat simpul atau tepi jika tidak ada, dan kemudian menambahkan atau memperbarui properti ke sana, terlepas dari apakah itu simpul atau tepi baru atau yang sudah ada.

Untuk menambah atau memodifikasi properti, gunakan `property()` langkah. Gunakan langkah ini di luar `coalesce()` langkah. Jika Anda mencoba memodifikasi properti simpul atau tepi yang ada di dalam `coalesce()` langkah, kueri mungkin tidak dioptimalkan oleh mesin kueri Neptunus.

Kueri berikut menambahkan atau memperbarui properti penghitung pada setiap simpul yang diupsert. Setiap `property()` langkah memiliki kardinalitas tunggal untuk memastikan bahwa nilai baru menggantikan nilai yang ada, daripada ditambahkan ke serangkaian nilai yang ada.

```
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()
```

Jika Anda memiliki nilai properti, seperti nilai `lastUpdated` stempel waktu, yang berlaku untuk semua elemen yang muncul, Anda dapat menambahkan atau memperbaruinya di akhir kueri:

```
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()
```

Jika ada kondisi tambahan yang menentukan apakah simpul atau tepi harus dimodifikasi lebih lanjut atau tidak, Anda dapat menggunakan `has()` langkah untuk memfilter elemen yang akan diterapkan modifikasi. Contoh berikut menggunakan `has()` langkah untuk memfilter simpul naik berdasarkan nilai properti mereka. `version` Kueri kemudian memperbarui ke 3 `version` dari setiap simpul yang `version` kurang dari 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()
```

# Menganalisis eksekusi kueri Neptune menggunakan `explain` Gremlin
<a name="gremlin-explain"></a>

Amazon Neptune telah menambahkan fitur Gremlin bernama *explain*. Fitur ini adalah alat swalayan untuk memahami pendekatan eksekusi yang diambil oleh mesin Neptune. Anda memintanya dengan menambahkan parameter `explain` ke panggilan HTTP yang mengirimkan kueri Gremlin.

Fitur `explain` menyediakan informasi tentang struktur logis rencana eksekusi kueri. Anda dapat menggunakan informasi ini untuk mengidentifikasi potensi evaluasi dan hambatan eksekusi dan menyetel kueri Anda, seperti yang dijelaskan dalam [Menyetel kueri Gremlin](gremlin-traversal-tuning.md). Anda juga dapat menggunakan [petunjuk kueri](gremlin-query-hints.md) untuk meningkatkan rencana eksekusi kueri.

**Topics**
+ [Memahami bagaimana kueri Gremlin bekerja di Neptune](gremlin-explain-background.md)
+ [Menggunakan API `explain` Gremlin di Neptune](gremlin-explain-api.md)
+ [API `profile` Gremlin di Neptune](gremlin-profile-api.md)
+ [Menyetel kueri Gremlin menggunakan `explain` dan `profile`](gremlin-traversal-tuning.md)
+ [Dukungan langkah Gremlin asli di Amazon Neptune](gremlin-step-support.md)

# Memahami bagaimana kueri Gremlin bekerja di Neptune
<a name="gremlin-explain-background"></a>

Untuk mengambil keuntungan penuh dari laporan `explain` dan `profile` Gremlin di Amazon Neptune, akan sangat membantu untuk memahami beberapa informasi latar belakang tentang kueri Gremlin.

**Topics**
+ [Pernyataan Gremlin di Neptune](gremlin-explain-background-statements.md)
+ [Bagaimana Neptune memproses kueri Gremlin menggunakan indeks pernyataan](gremlin-explain-background-indexing-examples.md)
+ [Bagaimana kueri Gremlin diproses di Neptune](gremlin-explain-background-querying.md)

# Pernyataan Gremlin di Neptune
<a name="gremlin-explain-background-statements"></a>

Data grafik properti di Amazon Neptune terdiri dari pernyataan empat-posisi (quad). Masing-masing pernyataan ini merupakan unit atom individu data grafik properti. Untuk informasi selengkapnya, lihat [Model Data Grafik Neptune](feature-overview-data-model.md). Mirip dengan model data Resource Description Framework (RDF), empat posisi ini adalah sebagai berikut:
+ `subject (S)`
+ `predicate (P)`
+ `object (O)`
+ `graph (G)`

Setiap pernyataan adalah penegasan tentang satu sumber daya atau lebih. Misalnya, sebuah pernyataan dapat menegaskan adanya hubungan antara dua sumber daya, atau dapat melampirkan properti (pasangan nilai-kunci) ke beberapa sumber daya.

Anda dapat menganggap predikat sebagai kata kerja pernyataan, menggambarkan jenis hubungan atau properti. Objeknya adalah target hubungan, atau nilai properti. Posisi grafik adalah opsional dan dapat digunakan dalam berbagai cara. Untuk data grafik properti (PG) Neptune, bisa tidak digunakan (grafik null) atau digunakan untuk mewakili pengidentifikasi untuk edge. Satu set pernyataan dengan pengidentifikasi sumber daya bersama menciptakan grafik.

Ada tiga kelas pernyataan dalam model data grafik properti Neptune:

**Topics**
+ [Pernyataan Label Vertex Gremlin](#gremlin-explain-background-vertex-labels)
+ [Pernyataan Edge](#gremlin-explain-background-edge-statements)
+ [Pernyataan Properti](#gremlin-explain-background-property-statements)

## Pernyataan Label Vertex Gremlin
<a name="gremlin-explain-background-vertex-labels"></a>

Pernyataan label Vertex di Neptune melayani dua tujuan:
+ Mereka melacak label untuk vertex.
+ Kehadiran setidaknya satu dari pernyataan ini adalah yang menyiratkan adanya vertex tertentu dalam grafik.

Subjek dari pernyataan ini adalah pengidentifikasi vertex, dan objeknya adalah label, yang keduanya ditentukan oleh pengguna. Anda menggunakan predikat tetap khusus untuk pernyataan ini, ditampilkan sebagai `<~label>`, dan pengidentifikasi grafik default (grafik null), ditampilkan sebagai `<~>`.

Contohnya, pertimbangkan traversal `addV` berikut ini.

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

Traversal ini menghasilkan pernyataan berikut yang ditambahkan ke grafik.

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

## Pernyataan Gremlin Edge
<a name="gremlin-explain-background-edge-statements"></a>

Sebuah pernyataan edge Gremlin adalah yang menyiratkan adanya edge antara dua vertex dalam grafik di Neptune. Subjek (S) dari pernyataan edge adalah vertex `from` sumber. Predikat (P) adalah label edge yang disediakan pengguna. Objek (O) adalah vertex `to` target. Grafik (G) adalah pengenal edge yang disediakan pengguna.

Contohnya, pertimbangkan traversal `addE` berikut ini.

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

Traversal menghasilkan pernyataan berikut yang ditambahkan ke grafik.

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

## Pernyataan Properti Gremlin
<a name="gremlin-explain-background-property-statements"></a>

Sebuah pernyataan properti Gremlin di Neptune menegaskan nilai properti individu untuk vertex atau edge. Subjek adalah pengidentifikasi vertex atau edge yang disediakan pengguna. Predikat adalah nama properti (kunci), dan objek adalah nilai properti individu. Grafik (G) adalah sekali lagi pengidentifikasi grafik default, grafik null, ditampilkan sebagai `<~>`.

Perhatikan contoh properti simpul berikut.

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

Pernyataan ini menghasilkan berikut ini.

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

Pernyataan properti berbeda dari yang lain dalam hal bahwa objek mereka adalah nilai primitif (`string`, `date`, `byte`, `short`, `int`, `long`, `float`, atau `double`). Objek mereka bukan pengidentifikasi sumber daya yang dapat digunakan sebagai subjek penegasan lain.

Untuk multi-properti, setiap nilai properti individu dalam set menerima pernyataannya sendiri.

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

Hal ini menyebabkan hal berikut ini.

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

Properti tepi ditangani mirip dengan properti simpul, tetapi gunakan pengenal tepi di posisi (S). Misalnya, menambahkan properti ke tepi:

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

Ini menghasilkan pernyataan berikut yang ditambahkan ke grafik.

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

# Bagaimana Neptune memproses kueri Gremlin menggunakan indeks pernyataan
<a name="gremlin-explain-background-indexing-examples"></a>

Pernyataam diakses di Amazon Neptune dengan cara tiga indeks pernyataan, seperti yang dijelaskan dalam [Bagaimana Pernyataan Diindeks di Neptune](feature-overview-storage-indexing.md). Neptune mengekstrak sebuah *pola* pernyataan dari kueri Gremlin di mana beberapa posisi diketahui, dan sisanya dibiarkan untuk penemuan oleh pencarian indeks.

Neptune mengasumsikan bahwa ukuran skema grafik properti tidak besar. Ini berarti bahwa jumlah label edge yang berbeda dan nama properti cukup rendah, sehingga jumlah predikat yang berbeda rendah. Neptune melacak predikat yang berbeda dalam indeks terpisah. Menggunakan cache predikat ini untuk melakukan pemindaian serikat `{ all P x POGS }` daripada menggunakan indeks OSGP. Menghindari kebutuhan untuk indeks OSGP traversal terbalik menghemat ruang penyimpanan dan throughput beban.

Neptunus Explain/Profile Gremlin API memungkinkan Anda mendapatkan jumlah predikat dalam grafik Anda. Anda kemudian dapat menentukan apakah aplikasi Anda membatalkan asumsi Neptune bahwa skema grafik properti Anda kecil.

Contoh berikut membantu menggambarkan bagaimana Neptune menggunakan indeks untuk memproses kueri Gremlin.

**Pertanyaan: Apa label simpul? `v1`**

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

**Pertanyaan: Apa tepi luar 'tahu' dari simpul? `v1`**

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

**Pertanyaan: Simpul mana yang memiliki label `Person` simpul?**

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

**Pertanyaan: Apa from/to simpul dari tepi yang diberikan? `e1`**

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

Satu indeks pernyataan yang **tidak** Neptune miliki adalah indeks OSGP traversal terbalik. Indeks ini dapat digunakan untuk mengumpulkan semua edge masuk di semua label edge, seperti dalam contoh berikut.

**Pertanyaan: Apa `v1` simpul yang berdekatan yang masuk?**

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

# Bagaimana kueri Gremlin diproses di Neptune
<a name="gremlin-explain-background-querying"></a>

Di Amazon Neptune, traversal yang lebih kompleks dapat diwakili oleh serangkaian pola yang menciptakan relasi berdasarkan definisi variabel bernama yang dapat dibagi di seluruh pola untuk membuat gabungan. Seperti yang ditunjukkan dalam contoh berikut.

**Pertanyaan: Apa lingkungan dua hop dari vertex? `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
```

Dengan berbagi variabel `?2` di dua pola (pada posisi O dalam pola pertama dan posisi S dari pola kedua), Anda membuat gabungan dari tetangga hop pertama ke tetangga hop kedua. [Setiap solusi Neptunus memiliki binding untuk tiga variabel bernama, yang dapat digunakan untuk membuat ulang TinkerPop Traverser (termasuk informasi jalur).](http://tinkerpop.apache.org/docs/current/reference/#_the_traverser)

```
```

[Langkah pertama dalam pemrosesan kueri Gremlin adalah mengurai kueri menjadi objek TinkerPop [Traversal](http://tinkerpop.apache.org/docs/current/reference/#traversal), yang terdiri dari serangkaian langkah. TinkerPop ](http://tinkerpop.apache.org/docs/current/reference/#graph-traversal-steps) Langkah-langkah ini, yang merupakan bagian dari [ TinkerPop proyek Apache](http://tinkerpop.apache.org/) open-source, adalah operator logis dan fisik yang menyusun traversal Gremlin dalam implementasi referensi. Keduanya digunakan untuk mewakili model kueri. Keduanya adalah operator yang dapat dieksekusi yang dapat menghasilkan solusi sesuai dengan semantik operator yang mereka wakili. Misalnya, keduanya `.V()` diwakili dan dieksekusi oleh TinkerPop [GraphStep](http://tinkerpop.apache.org/docs/current/reference/#graph-step).

Karena off-the-shelf TinkerPop langkah-langkah ini dapat dieksekusi, TinkerPop Traversal semacam itu dapat mengeksekusi kueri Gremlin apa pun dan menghasilkan jawaban yang benar. Namun, ketika dieksekusi terhadap grafik besar, TinkerPop langkah-langkah terkadang bisa sangat tidak efisien dan lambat. Alih-alih menggunakannya, Neptune mencoba mengubah traversal menjadi bentuk deklaratif yang terdiri dari grup pola, seperti yang dijelaskan sebelumnya.

Neptune saat ini tidak mendukung semua operator (langkah) Gremlin di mesin kueri aslinya. Jadi Neptune mencoba melakukan collaps pada sebanyak mungkin langkah ke dalam satu `NeptuneGraphQueryStep`, yang berisi rencana kueri logis deklaratif untuk semua langkah-langkah yang telah dikonversi. Idealnya, semua langkah dikonversi. Tetapi ketika sebuah langkah ditemukan yang tidak dapat dikonversi, Neptunus keluar dari eksekusi asli dan menunda semua eksekusi kueri dari titik itu ke langkah-langkahnya. TinkerPop Neptune tidak mencoba untuk menjalin masuk dan keluar dari eksekusi asli.

Setelah langkah-langkah diterjemahkan ke dalam rencana kueri logis, Neptune menjalankan serangkaian pengoptimal kueri yang menulis ulang rencana kueri berdasarkan analisis statis dan perkiraan kardinalitas. Pengoptimal ini melakukan hal-hal seperti mengatur ulang operator berdasarkan jumlah rentang, memangkas operator yang tidak perlu atau berlebihan, mengatur ulang filter, mendorong operator ke dalam kelompok yang berbeda, dan sebagainya.

Setelah rencana kueri yang dioptimalkan diproduksi, Neptune menciptakan alur operator fisik yang melakukan pekerjaan mengeksekusi kueri. Ini termasuk membaca data dari indeks pernyataan, melakukan penggabungan berbagai jenis, penyaringan, pengurutan, dan sebagainya. Pipeline menghasilkan aliran solusi yang kemudian diubah kembali menjadi aliran objek TinkerPop Traverser.

## Serialisasi hasil kueri
<a name="gremlin-explain-background-querying-serialization"></a>

Amazon Neptunus saat ini mengandalkan TinkerPop serializer pesan respons untuk mengonversi hasil kueri TinkerPop (Traversers) menjadi data serial untuk dikirim melalui kabel kembali ke klien. Format serialisasi ini cenderung cukup verbose.

Sebagai contoh, untuk melakukan serialisasi hasil dari kueri vertex seperti `g.V().limit(1)`, mesin kueri Neptune harus melakukan pencarian tunggal untuk memproduksi hasil kueri. Namun, serializer `GraphSON` akan melakukan sejumlah besar pencarian tambahan untuk mengemas vertex ke dalam format serialisasi. Serializer harus melakukan satu pencarian untuk mendapatkan label, satu pencarian untuk mendapatkan kunci properti, dan satu pencarian per kunci properti untuk vertex untuk mendapatkan semua nilai untuk setiap kunci.

Beberapa format serialisasi lebih efisien, tetapi semua memerlukan pencarian tambahan. Selain itu, TinkerPop serializer tidak mencoba menghindari penelusuran duplikat, seringkali mengakibatkan banyak pencarian diulang secara tidak perlu.

Hal ini membuat sangat penting untuk menulis kueri Anda sehingga mereka meminta secara khusus hanya untuk informasi yang mereka butuhkan. Misalnya, `g.V().limit(1).id()` akan mengembalikan hanya ID vertex dan menghilangkan semua pencarian serializer tambahan. [API `profile` Gremlin di Neptune](gremlin-profile-api.md) memungkinkan Anda untuk melihat berapa banyak panggilan pencarian yang dilakukan selama eksekusi kueri dan selama serialisasi.

# Menggunakan API `explain` Gremlin di Neptune
<a name="gremlin-explain-api"></a>

API `explain` Gremlin Amazon Neptune mengembalikan rencana kueri yang akan dieksekusi jika kueri tertentu dijalankan. Karena API tidak benar-benar menjalankan kueri, rencana dikembalikan hampir seketika.

Ini berbeda dari langkah TinkerPop .explain () sehingga dapat melaporkan informasi khusus ke mesin Neptunus.

## Informasi yang terkandung dalam laporan `explain` Gremlin
<a name="gremlin-explain-api-results"></a>

Laporan `explain` berisi informasi berikut:
+ String kueri seperti yang diminta.
+ **Traversal asli.** Ini adalah objek TinkerPop Traversal yang dihasilkan dengan mengurai string kueri menjadi beberapa TinkerPop langkah. Ini setara dengan kueri asli yang dihasilkan dengan menjalankan `.explain()` kueri terhadap kueri TinkerPop TinkerGraph.
+ **Traversal yang dikonversi.** Ini adalah Traversal Neptunus yang dihasilkan dengan mengubah TinkerPop Traversal menjadi representasi rencana kueri logis Neptunus. Dalam banyak kasus, seluruh TinkerPop traversal diubah menjadi dua langkah Neptunus: satu yang mengeksekusi seluruh query `NeptuneGraphQueryStep` () dan satu yang mengubah output mesin kueri Neptunus kembali menjadi Traversers (). TinkerPop `NeptuneTraverserConverterStep`
+ **Traversal yang dioptimalkan.** Ini adalah versi yang dioptimalkan dari rencana kueri Neptune setelah dijalankan melalui serangkaian pengoptimalan mengurangi kerja statis yang menulis ulang kueri berdasarkan analisis statis dan perkiraan kardinalitas. Pengoptimal ini melakukan hal-hal seperti mengatur ulang operator berdasarkan jumlah rentang, memangkas operator yang tidak perlu atau berlebihan, mengatur ulang filter, mendorong operator ke dalam kelompok yang berbeda, dan sebagainya.
+ **Hitungan predikat.** Karena strategi pengindeksan Neptune yang dijelaskan sebelumnya, memiliki sejumlah besar predikat yang berbeda dapat menyebabkan masalah performa. Hal ini terutama berlaku untuk kueri yang menggunakan operator traversal terbalik tanpa label edge (`.in` atau `.both`). Jika operator tersebut digunakan dan jumlah predikat cukup tinggi, `explain` menampilkan pesan peringatan.
+ **Informasi DFE.** Ketika mesin alternatif DFE diaktifkan, komponen traversal berikut mungkin muncul dalam traversal yang dioptimalkan:
  + **`DFEStep`**— Langkah DFE Neptunus yang dioptimalkan dalam traversal yang berisi anak. `DFENode` `DFEStep`merupakan bagian dari rencana kueri yang dijalankan di mesin DFE.
  + **`DFENode`**— Berisi representasi menengah sebagai satu atau lebih anak`DFEJoinGroupNodes`.
  + **`DFEJoinGroupNode`**— Merupakan gabungan dari satu atau lebih `DFENode` atau `DFEJoinGroupNode` elemen.
  + **`NeptuneInterleavingStep`**— Langkah DFE Neptunus yang dioptimalkan dalam traversal yang berisi anak. `DFEStep`

    Juga berisi `stepInfo` elemen yang berisi informasi tentang traversal, seperti elemen perbatasan, elemen jalur yang digunakan, dan sebagainya. Informasi ini digunakan untuk memproses anak`DFEStep`.

  Cara mudah untuk mengetahui apakah permintaan Anda sedang dievaluasi oleh DFE adalah memeriksa apakah output `explain` berisi `DFEStep`. Setiap bagian dari traversal yang bukan bagian dari tidak `DFEStep` akan dieksekusi oleh DFE dan akan dieksekusi oleh mesin. TinkerPop 

  Lihat [Contoh dengan DFE diaktifkan](#gremlin-explain-dfe) untuk laporan contoh.

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

Sintaks API `explain` sama seperti untuk API HTTP untuk kueri, kecuali bahwa ia menggunakan `/gremlin/explain` sebagai titik akhir, bukan `/gremlin`, seperti pada contoh berikut.

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

Kueri sebelumnya akan menghasilkan output berikut.

```
*******************************************************
                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
```

## Langkah Belum Dikonversi TinkerPop
<a name="gremlin-explain-unconverted-steps"></a>

Idealnya, semua TinkerPop langkah dalam traversal memiliki cakupan operator Neptunus asli. Ketika ini tidak terjadi, Neptunus kembali TinkerPop pada eksekusi langkah untuk kesenjangan dalam jangkauan operatornya. Jika traversal menggunakan langkah yang belum Neptune miliki cakupan aslinya, laporan `explain` menampilkan peringatan yang menunjukkan dimana kesenjangan terjadi.

Ketika sebuah langkah tanpa operator Neptunus asli yang sesuai ditemukan, seluruh traversal dari titik itu ke depan dijalankan TinkerPop menggunakan langkah-langkah, bahkan jika langkah selanjutnya memang memiliki operator Neptunus asli.

Pengecualian untuk ini adalah ketika pencarian teks lengkap Neptune dipanggil. NeptuneSearchStep Mengimplementasikan langkah-langkah tanpa padanan asli sebagai langkah pencarian teks lengkap.

## Contoh output `explain` di mana semua langkah dalam kueri memiliki ekuivalen asli
<a name="gremlin-explain-all-steps-converted"></a>

Berikut ini adalah contoh laporan `explain` untuk kueri di mana semua langkah memiliki ekuivalen asli:

```
*******************************************************
                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
```

## Contoh di mana beberapa langkah dalam kueri tidak memiliki ekuivalen asli
<a name="gremlin-explain-not-all-steps-converted"></a>

Neptune menangani `GraphStep` dan `VertexStep` secara native, tetapi jika Anda memperkenalkan `FoldStep` dan `UnfoldStep`, output `explain` yang dihasilkan berbeda:

```
*******************************************************
                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
```

Dalam hal ini, `FoldStep` menghentikan Anda dari eksekusi asli. Namun bahkan `VertexStep` berikutnya tidak lagi ditangani secara native karena muncul hilir dari langkah `Fold/Unfold`.

Untuk kinerja dan penghematan biaya, penting bagi Anda untuk mencoba merumuskan traversal sehingga jumlah maksimum pekerjaan yang mungkin dilakukan secara asli di dalam mesin kueri Neptunus, bukan dengan implementasi langkah. TinkerPop 

## Contoh kueri yang menggunakan Neptunus full-text-search
<a name="gremlin-explain-full-text-search-steps"></a>

Kueri berikut menggunakan pencarian teks lengkap 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*")
```

Bagian `.has("name", "Neptune#fts mark*")` membatasi pencarian ke vertex dengan `name`, sementara `.has("Person", "name", "Neptune#fts mark*")` membatasi pencarian ke vertex dengan `name` dan label `Person`. Hal ini menghasilkan traversal berikut di laporan `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}
    }
}]
```

## Contoh penggunaan `explain` saat DFE diaktifkan
<a name="gremlin-explain-dfe"></a>

Berikut ini adalah contoh laporan `explain` ketika mesin kueri alternatif DFE diaktifkan:

```
*******************************************************
                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
```

Lihat [Informasi di `explain`](#gremlin-explain-api-results) untuk deskripsi bagian spesifik DFE dalam laporan.

# API `profile` Gremlin di Neptune
<a name="gremlin-profile-api"></a>

API `profile` Gremlin Neptune menjalankan traversal Gremlin, mengumpulkan berbagai metrik tentang proses, dan menghasilkan laporan profil sebagai output.

Ini berbeda dari TinkerPop langkah.profile () sehingga dapat melaporkan informasi khusus untuk mesin Neptunus.

Laporan profil mencakup informasi berikut tentang rencana kueri:
+ Alur operator fisik
+ Operasi indeks untuk eksekusi dan serialisasi kueri
+ Ukuran hasilnya

API `profile` menggunakan versi diperpanjang dari sintaks HTTP API untuk kueri, dengan `/gremlin/profile` sebagai titik akhir alih-alih `/gremlin`.

## Parameter khusus untuk `profile` Gremlin Neptune
<a name="gremlin-profile-api-parameters"></a>
+ **profile.results** — `boolean`, nilai yang diizinkan: `TRUE` dan `FALSE`, nilai default: `TRUE`.

  Jika true, hasil kueri dikumpulkan dan ditampilkan sebagai bagian dari laporan `profile`. Jika false, hanya jumlah hasil yang ditampilkan.
+ **profile.chop** — `int`, nilai default: 250.

  Jika non-nol, menyebabkan hasil string akan dipotong pada jumlah karakter tersebut. Hal ini tidak menjaga semua hasil dari ditangkap. Ini hanya membatasi ukuran string dalam laporan profil. Jika diatur ke nol, string berisi semua hasil.
+ **profile.serializer** – `string`, nilai default: `<null>`.

  Jika non-null, hasil yang dikumpulkan dikembalikan dalam pesan respons serial dalam format yang ditentukan oleh parameter ini. Jumlah operasi indeks yang diperlukan untuk menghasilkan pesan respons dilaporkan bersama dengan ukuran dalam byte yang akan dikirim ke klien.

  Nilai yang diizinkan adalah `<null>` atau salah satu jenis MIME yang valid atau nilai enum “Serializers” TinkerPop driver.

  ```
  "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`, nilai yang diizinkan: `TRUE` dan `FALSE`, nilai default: `FALSE`.

  Jika true, menunjukkan laporan detail dari semua operasi indeks yang terjadi selama eksekusi dan serialisasi kueri. Peringatan: Laporan ini bisa verbose.



## Contoh output dari `profile` Gremlin Neptune
<a name="gremlin-profile-sample-output"></a>

Berikut ini adalah sampel kueri `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"}'
```

Query ini menghasilkan laporan `profile` berikut ketika dieksekusi pada grafik sampel rute udara dari posting blog, [Mari Saya Grafikkan Untuk Anda - Bagian 1 - Rute Udara](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
```

Selain rencana kueri dikembalikan oleh panggilan ke Neptune `explain`, hasil `profile` menyertakan statistik runtime sekitar eksekusi kueri. Setiap operasi Gabungan ditandai dengan waktu yang dibutuhkan untuk melakukan penggabungannya serta jumlah sebenarnya dari solusi yang melewatinya.

Output `profile` menyertakan waktu yang dibutuhkan selama fase eksekusi kueri inti, serta fase serialisasi jika opsi `profile.serializer` telah ditentukan.

Rincian operasi indeks yang dilakukan selama setiap fase juga disertakan di bagian bawah output `profile`.

Perhatikan bahwa proses berturut-turut dari kueri yang sama dapat menunjukkan hasil yang berbeda dalam hal operasi run-time dan indeks karena caching.

Untuk kueri yang menggunakan langkah `repeat()`, rincian perbatasan pada setiap iterasi tersedia jika langkah `repeat()` didorong ke bawah sebagai bagian dari `NeptuneGraphQueryStep`.

## Perbedaan dalam laporan `profile` saat DFE diaktifkan
<a name="gremlin-profile-dfe-output"></a>

Ketika mesin kueri alternatif Neptune DFE diaktifkan, output `profile` agak berbeda:

**Dioptimalkan oleh Traversal:** Bagian ini serupa dengan yang ada di output `explain`, tetapi berisi informasi tambahan. Ini menyertakan jenis operator DFE yang dipertimbangkan dalam perencanaan, dan kasus terburuk terkait dan perkiraan biaya kasus terbaik.

**Physical Pipeline:** Bagian ini menangkap operator yang digunakan untuk mengeksekusi query. `DFESubQuery`elemen abstrak rencana fisik yang digunakan oleh DFE untuk melaksanakan bagian dari rencana yang menjadi tanggung jawabnya. `DFESubQuery`Elemen-elemen tersebut dibuka di bagian berikut di mana statistik DFE terdaftar.

**DFEQueryStatistik Mesin:** Bagian ini muncul hanya ketika setidaknya sebagian dari kueri dijalankan oleh DFE. Ini menguraikan berbagai statistik runtime yang khusus untuk DFE, dan berisi rincian rinci dari waktu yang dihabiskan di berbagai bagian eksekusi kueri, oleh. `DFESubQuery`

Subquery bersarang dalam `DFESubQuery` elemen yang berbeda diratakan di bagian ini, dan pengidentifikasi unik ditandai dengan header yang dimulai dengan. `subQuery=`

**Metrik Traversal:** Bagian ini menunjukkan metrik traversal tingkat langkah, dan ketika mesin DFE menjalankan semua atau sebagian kueri, menampilkan metrik untuk dan/atau. `DFEStep` `NeptuneInterleavingStep` Lihat [Menyetel kueri Gremlin menggunakan `explain` dan `profile`](gremlin-traversal-tuning.md).

**catatan**  
DFE adalah fitur eksperimental yang dirilis dalam mode lab, format tepat output `profile` dapat berubah.

## Sampel output `profile` ketika Neptune Dataflow engine (DFE) diaktifkan
<a name="gremlin-profile-sample-dfe-output"></a>

Ketika mesin DFE sedang digunakan untuk menjalankan query Gremlin, output dari diformat seperti yang [API `profile` Gremlin](#gremlin-profile-api) ditunjukkan pada contoh di bawah ini.

Kueri:

```
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
```

**catatan**  
Karena mesin DFE adalah fitur eksperimental yang dirilis dalam mode lab, format `profile` output yang tepat dapat berubah.

# Menyetel kueri Gremlin menggunakan `explain` dan `profile`
<a name="gremlin-traversal-tuning"></a>

[[Anda sering dapat menyetel kueri Gremlin Anda di Amazon Neptunus untuk mendapatkan kinerja yang lebih baik, menggunakan informasi yang tersedia untuk Anda dalam laporan yang Anda dapatkan dari penjelasan dan profil Neptunus.](gremlin-profile-api.md)](gremlin-explain-api.md) APIs Untuk melakukannya, ia membantu untuk memahami bagaimana Neptune memproses traversals Gremlin.

**penting**  
Perubahan dibuat di TinkerPop versi 3.4.11 yang meningkatkan kebenaran bagaimana kueri diproses, tetapi untuk saat ini terkadang dapat berdampak serius pada kinerja kueri.  
Misalnya, kueri semacam ini dapat berjalan jauh lebih lambat:  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  out()
```
Simpul setelah langkah batas sekarang diambil dengan cara yang tidak optimal karena perubahan 3.4.11. TinkerPop Untuk menghindari hal ini, Anda dapat memodifikasi kueri dengan menambahkan langkah penghalang () kapan saja setelah`order().by()`. Contoh:  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  barrier().
  out()
```
TinkerPop [3.4.11 diaktifkan di mesin Neptunus versi 1.0.5.0.](engine-releases-1.0.5.0.md)

## Memahami pemrosesan traversal Gremlin di Neptune
<a name="gremlin-traversal-processing"></a>

Ketika traversal Gremlin dikirim ke Neptune, ada tiga proses utama yang mengubah traversal menjadi rencana eksekusi yang mendasari untuk dieksekusi mesin. Ketiganya adalah parsing, conversion, dan optimization:

![\[3 proses mengubah kueri Gremlin menjadi rencana eksekusi.\]](http://docs.aws.amazon.com/id_id/neptune/latest/userguide/images/Gremlin_traversal_processing.png)


### Proses penguraian traversal
<a name="gremlin-traversal-processing-parsing"></a>

Langkah pertama dalam memproses traversal adalah mengurainya ke dalam bahasa yang sama. [Di Neptunus, bahasa umum itu adalah serangkaian langkah yang merupakan bagian TinkerPop dari API. TinkerPop](http://tinkerpop.apache.org/javadocs/3.4.8/full/org/apache/tinkerpop/gremlin/process/traversal/Step.html) Masing-masing langkah ini merupakan unit komputasi dalam traversal.

Anda dapat mengirim traversal Gremlin ke Neptune baik sebagai string atau sebagai bytecode. Titik akhir REST dan metode `submit()` driver klien Java mengirim traversals sebagai string, seperti dalam contoh ini:

```
client.submit("g.V()")
```

Driver aplikasi dan bahasa yang menggunakan [Varian bahasa Gremlin (GLV)](https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/) mengirim traversals dalam bytecode.

### Proses konversi traversal
<a name="gremlin-traversal-processing-conversion"></a>

Langkah kedua dalam memproses traversal adalah mengubah TinkerPop langkah-langkahnya menjadi serangkaian langkah Neptunus yang dikonversi dan tidak dikonversi. Sebagian besar langkah dalam bahasa kueri Apache TinkerPop Gremlin dikonversi ke langkah-langkah khusus Neptunus yang dioptimalkan untuk dijalankan pada mesin Neptunus yang mendasarinya. Ketika sebuah TinkerPop langkah tanpa ekuivalen Neptunus ditemui dalam traversal, langkah itu dan semua langkah selanjutnya dalam traversal diproses oleh mesin kueri. TinkerPop 

Untuk informasi selengkapnya tentang langkah-langkah apa yang dapat dikonversi dalam keadaan apa, lihat [Dukungan langkah Gremlin](gremlin-step-support.md).

### Proses optimasi traversal
<a name="gremlin-traversal-processing-optimization"></a>

Langkah terakhir dalam pemrosesan traversal adalah menjalankan serangkaian langkah dikonversi dan non-dikonversi melalui optimizer, untuk mencoba menentukan rencana eksekusi terbaik. Output dari optimasi ini adalah rencana eksekusi yang diproses mesin Neptune.

## Menggunakan API `explain` Gremlin Neptune untuk menyetel kueri
<a name="gremlin-traversal-tuning-explain"></a>

API explain Neptune tidak sama dengan langkah `explain()` Gremlin. Ia mengembalikan rencana eksekusi akhir yang akan diproses mesin Neptune ketika mengeksekusi kueri. Karena tidak melakukan pemrosesan apa pun, ia mengembalikan rencana yang sama terlepas dari parameter yang digunakan, dan outputnya tidak mengandung statistik tentang eksekusi aktual.

Pertimbangkan traversal sederhana berikut yang menemukan semua vertex bandara untuk Anchorage:

```
g.V().has('code','ANC')
```

Ada dua cara untuk menjalankan traversal ini melalui API `explain` Neptune. Cara pertama adalah untuk membuat panggilan REST ke titik akhir explain, seperti ini:

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

Cara kedua adalah menggunakan workbench cell magic [%%gremlin](notebooks-magics.md#notebooks-cell-magics-gremlin) Neptune dengan parameter `explain`. Ini melewati traversal yang terkandung dalam tubuh sel ke API `explain` Neptune dan kemudian menampilkan output yang dihasilkan ketika Anda menjalankan sel:

```
%%gremlin explain

g.V().has('code','ANC')
```

Output `explain` API yang dihasilkan menjelaskan rencana eksekusi Neptunus untuk traversal. Seperti yang bisa Anda lihat pada gambar di bawah ini, rencananya mencakup masing-masing dari 3 langkah dalam alur pemrosesan:

![\[Output API explain untuk traversal Gremlin sederhana.\]](http://docs.aws.amazon.com/id_id/neptune/latest/userguide/images/Gremlin_explain_output_1.png)


### Penyetelan traversal dengan melihat langkah-langkah yang tidak dikonversi
<a name="gremlin-traversal-tuning-explain-non-converted-steps"></a>

Salah satu hal pertama yang harus dicari di output API `explain` Neptune adalah untuk langkah-langkah Gremlin yang tidak dikonversi ke langkah asli Neptune. Dalam rencana kueri, ketika langkah yang ditemui tidak dapat dikonversi ke langkah asli Neptune, langkah tersebut dan semua langkah berikutnya dalam rencana diproses oleh server Gremlin.

Dalam contoh di atas, semua langkah dalam traversal dikonversi. Mari kita periksa output API `explain` untuk traversal ini:

```
g.V().has('code','ANC').out().choose(hasLabel('airport'), values('code'), constant('Not an airport'))
```

Seperti yang bisa Anda lihat pada gambar di bawah ini, Neptune tidak bisa mengonversi langkah `choose()`:

![\[Output API explain di mana tidak semua langkah dapat dikonversi.\]](http://docs.aws.amazon.com/id_id/neptune/latest/userguide/images/Gremlin_explain_output_2.png)


Ada beberapa hal yang dapat Anda lakukan untuk menyetel performa traversal. Yang pertama adalah menulis ulang sedemikian rupa untuk menghilangkan langkah yang tidak dapat dikonversi. Lainnya adalah memindahkan langkah ke akhir traversal sehingga semua langkah lain dapat dikonversi ke yang asli.

Rencana kueri dengan langkah-langkah yang tidak dikonversi tidak selalu perlu disetel. Jika langkah-langkah yang tidak dapat dikonversi berada di akhir traversal, dan terkait dengan bagaimana output diformat alih-alih bagaimana grafik ditraversalkan, langkah mungkin memiliki sedikit efek pada performa.

### 
<a name="gremlin-traversal-tuning-explain-unindexed-lookups"></a>

Hal lain yang harus dicari ketika memeriksa output dari API `explain` Neptune adalah langkah-langkah yang tidak menggunakan indeks. Traversal berikut menemukan semua bandara dengan penerbangan yang mendarat di Anchorage:

```
g.V().has('code','ANC').in().values('code')
```

Output dari API explain untuk traversal ini adalah:

```
*******************************************************
                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
```

Pesan `WARNING` di bagian bawah output terjadi karena langkah `in()` dalam traversal tidak dapat ditangani menggunakan salah satu dari 3 indeks yang Neptune pertahankan (lihat [Bagaimana Pernyataan Diindeks di Neptune](feature-overview-storage-indexing.md) dan [Pernyataan Gremlin di Neptune](gremlin-explain-background-statements.md)). Karena langkah `in()` tidak berisi filter edge, langkah itu tidak dapat diselesaikan menggunakan indeks `SPOG`, `POGS` atau `GPSO`. Sebaliknya, Neptune harus melakukan pemindaian serikat untuk menemukan vertex yang diminta, yang jauh lebih efisien.

Ada dua cara untuk menyetel traversal dalam situasi ini. Yang pertama adalah menambahkan satu atau lebih kriteria penyaringan ke langkah `in()` sehingga pencarian yang diindeks dapat digunakan untuk menyelesaikan kueri. Untuk contoh di atas, ini mungkin:

```
g.V().has('code','ANC').in('route').values('code')
```

Output dari API `explain` Neptune untuk traversal yang direvisi tidak lagi berisi pesan `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
```

Pilihan lain jika Anda menjalankan banyak traversals semacam ini adalah untuk menjalankan traversal tersebut dalam sebuah klaster DB Neptune yang memiliki indeks `OSGP` opsional diaktifkan (lihat [Mengaktifkan Indeks OSGP](feature-overview-storage-indexing.md#feature-overview-storage-indexing-osgp)). Mengaktifkan indeks `OSGP` memiliki kelemahan:
+ Indeks ini harus diaktifkan dalam klaster DB sebelum data dimuat.
+ Tingkat penyisipan untuk vertex dan edge dapat melambat hingga 23%.
+ Penggunaan penyimpanan akan meningkat sekitar 20%.
+ Kueri Baca yang menyebarkan permintaan di semua indeks mungkin telah meningkatkan latensi.

Memiliki indeks `OSGP` lebih masuk akal untuk serangkaian pola kueri terbatas, tetapi kecuali jika Anda sering menjalankannya, biasanya lebih baik untuk mencoba untuk memastikan bahwa traversals yang Anda tulis dapat diselesaikan menggunakan tiga indeks utama.

### Menggunakan jumlah besar predikat
<a name="gremlin-traversal-tuning-explain-many-predicates"></a>

Neptune memperlakukan setiap label edge dan setiap nama properti vertex atau edge yang berbeda dalam grafik Anda sebagai predikat, dan dirancang secara default untuk bekerja dengan jumlah predikat berbeda yang relatif rendah. Bila Anda memiliki lebih dari beberapa ribu predikat dalam data grafik Anda, performa dapat menurun.

Output `explain` Neptune akan memperingatkan Anda jika hal ini terjadi:

```
Predicates
==========
# of predicates: 9549
WARNING: high predicate count (# of distinct property names and edge labels)
```

Jika tidak nyaman untuk mengulang pengerjaan model data Anda untuk mengurangi jumlah label dan properti, dan karenanya jumlah predikatnya, cara terbaik untuk menyetel traversal adalah menjalankannya dalam sebuah klaster DB yang memiliki indeks `OSGP` diaktifkan, seperti yang dibahas di atas.

## Menggunakan API `profile` Gremlin Neptune untuk menyetel traversal
<a name="gremlin-traversal-tuning-profile"></a>

API `profile` Neptune sangat berbeda dari langkah `profile()` Gremlin. Seperti halnya API `explain`, outputnya mencakup rencana kueri yang digunakan mesin Neptune saat mengeksekusi traversal. Selain itu, output `profile` menyertakan statistik eksekusi aktual untuk traversal, mengingat bagaimana parameternya ditetapkan.

Sekali lagi, ambil traversal sederhana yang menemukan semua vertex bandara untuk Anchorage:

```
g.V().has('code','ANC')
```

Seperti halnya dengan API `explain`, Anda dapat memanggil API `profile` menggunakan panggilan REST:

```
curl -X POST https://your-neptune-endpoint:port/gremlin/profile -d '{"gremlin":"g.V().has('code','ANC')"}'
```

Anda juga menggunakan workbench cell magic [%%gremlin](notebooks-magics.md#notebooks-cell-magics-gremlin) Neptune dengan parameter `profile`. Ini melewati traversal yang terkandung dalam tubuh sel ke API `profile` Neptune dan kemudian menampilkan output yang dihasilkan ketika Anda menjalankan sel:

```
%%gremlin profile

g.V().has('code','ANC')
```

Output `profile` API yang dihasilkan berisi rencana eksekusi Neptunus untuk traversal dan statistik tentang eksekusi rencana, seperti yang Anda lihat pada gambar ini:

![\[Contoh output API profile Neptune.\]](http://docs.aws.amazon.com/id_id/neptune/latest/userguide/images/Gremlin_profile_output_1.png)


Dalam output `profile`, bagian rencana eksekusi hanya berisi rencana eksekusi akhir untuk traversal, bukan langkah menengahnya. Bagian alur berisi operasi alur fisik yang dilakukan serta waktu aktual (dalam milidetik) yang diperlukan eksekusi traversal. Metrik runtime sangat membantu dalam membandingkan waktu yang diperlukan dua versi traversal yang berbeda saat Anda mengoptimalkan mereka.

**catatan**  
Runtime awal traversal umumnya lebih panjang dari runtime berikutnya, karena yang pertama menyebabkan data yang relevan untuk di-cache.

Bagian ketiga dari output `profile` berisi statistik eksekusi dan hasil traversal. Untuk melihat bagaimana informasi ini dapat berguna dalam menyetel traversal, pertimbangkan traversal berikut, yang menemukan setiap bandara yang namanya dimulai dengan “Anchora”, dan semua bandara yang dapat dijangkau dalam dua hop dari bandara tersebut, mengembalikan kode bandara, rute penerbangan, dan jarak:

```
%%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'))
```

### Metrik traversal di output API `profile` Neptune
<a name="gremlin-traversal-tuning-profile-traversal-metrics"></a>

Set pertama metrik yang tersedia di semua output `profile` adalah metrik traversal. Ini mirip dengan metrik langkah `profile()` Gremlin, dengan beberapa perbedaan:

```
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        -
```

Kolom pertama dari tabel traversal-metrik mencantumkan langkah-langkah yang dijalankan oleh traversal. Dua langkah pertama umumnya adalah langkah-langkah khusus Neptune, `NeptuneGraphQueryStep` dan `NeptuneTraverserConverterStep`.

`NeptuneGraphQueryStep` mewakili waktu eksekusi untuk seluruh bagian dari traversal yang dapat dikonversi dan dieksekusi secara native oleh mesin Neptune.

`NeptuneTraverserConverterStep`mewakili proses mengubah output dari langkah-langkah yang dikonversi tersebut menjadi TinkerPop traversers yang memungkinkan langkah-langkah yang tidak dapat dikonversi langkah-langkah, jika ada, untuk diproses, atau untuk mengembalikan hasil dalam format -kompatibel. TinkerPop

Pada contoh di atas, kita memiliki beberapa langkah yang tidak dikonversi, jadi kita melihat bahwa masing-masing TinkerPop langkah ini (`ProjectStep`,`PathStep`) kemudian muncul sebagai baris dalam tabel.

[Kolom kedua dalam tabel`Count`,, melaporkan jumlah pelintas yang *diwakili* yang melewati langkah, sedangkan kolom ketiga,`Traversers`, melaporkan jumlah pelintas yang melewati langkah itu, seperti yang dijelaskan dalam dokumentasi langkah profil. TinkerPop](https://tinkerpop.apache.org/docs/current/reference/#profile-step)

Dalam contoh kita ada 3.856 simpul dan 3.856 traversers dikembalikan oleh`NeptuneGraphQueryStep`, dan angka-angka ini tetap sama sepanjang pengolahan yang tersisa karena`ProjectStep`dan`PathStep`memformat hasil, tidak menyaring mereka.

**catatan**  
Tidak seperti TinkerPop, mesin Neptunus tidak mengoptimalkan kinerja *dengan* menumpuk di langkah-langkahnya. `NeptuneGraphQueryStep` `NeptuneTraverserConverterStep` Bulking adalah TinkerPop operasi yang menggabungkan pelintas pada simpul yang sama untuk mengurangi overhead operasional, dan itulah yang menyebabkan dan angka berbeda. `Count` `Traversers` Karena bulking hanya terjadi pada langkah-langkah yang didelegasikan Neptunus, dan bukan pada langkah-langkah yang TinkerPop ditangani Neptunus secara asli, kolom dan kolom jarang berbeda. `Count` `Traverser`

Kolom Waktu melaporkan jumlah milidetik yang diambil langkah, dan kolom `% Dur` melaporkan berapa persen dari total waktu pemrosesan yang diambil langkah. Ini adalah metrik yang memberi tahu Anda tempat untuk memfokuskan upaya penyetelan dengan menunjukkan langkah-langkah yang memakan waktu paling lama.

### Metrik operasi indeks di output API `profile` Neptune
<a name="gremlin-traversal-tuning-profile-index-operations"></a>

Satu set metrik dalam output dari API profil Neptune adalah operasi indeks:

```
Index Operations
================
Query execution:
    # of statement index ops: 23191
    # of unique statement index ops: 5960
    Duplication ratio: 3.89
    # of terms materialized: 0
```

Laporan ini:
+ Jumlah total pencarian indeks.
+ Jumlah pencarian indeks unik yang dilakukan.
+ Rasio total pencarian indeks ke yang unik. Rasio yang lebih rendah menunjukkan redundansi yang lebih sedikit.
+ Jumlah istilah terwujud dari kamus istilah.

### Metrik repeat di output API `profile` Neptune
<a name="gremlin-traversal-tuning-profile-repeat-metrics"></a>

Jika traversal Anda menggunakan `repeat()` seperti pada contoh di atas, maka bagian yang berisi metrik repeat muncul di output `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
```

Laporan ini:
+ Jumlah loop untuk satu baris (kolom `Iteration`).
+ Jumlah elemen yang dikunjungi oleh loop (kolom `Visited`).
+ Jumlah elemen yang dioutput oleh loop (kolom `Output`).
+ Elemen terakhir yang dioutput oleh loop (kolom `Until`).
+ Jumlah elemen yang dikeluarkan oleh loop (kolom `Emit`).
+ Jumlah elemen yang dilewatkan dari loop ke loop berikutnya (kolom `Next`).

Metrik repeat ini sangat membantu dalam memahami faktor percabangan traversal Anda, untuk mendapatkan kesan berapa banyak pekerjaan yang sedang dilakukan oleh database. Anda dapat menggunakan angka-angka ini untuk mendiagnosis masalah performa, terutama ketika traversal yang sama berkinerja berbeda secara dramatis dengan parameter lainnya.

### Metrik pencarian teks lengkap di output API `profile` Neptune
<a name="gremlin-traversal-tuning-profile-fts-metrics"></a>

Ketika sebuah traversal menggunakan [pencarian teks penuh](full-text-search.md) seperti dalam contoh di atas, maka bagian yang berisi metrik pencarian teks lengkap (FTS) muncul di output `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
```

Ini menunjukkan kueri yang dikirim ke klaster ElasticSearch (ES) dan melaporkan beberapa metrik tentang interaksi yang dapat membantu Anda menentukan masalah kinerja ElasticSearch yang berkaitan dengan penelusuran teks lengkap:
+ Ringkasan informasi tentang panggilan ke ElasticSearch indeks:
  + Jumlah total milidetik yang dibutuhkan oleh semua remoteCalls untuk memenuhi kueri (`total`).
  + Jumlah rata-rata milidetik yang dihabiskan di remoteCall (`avg`).
  + Jumlah minimum milidetik yang dihabiskan di remoteCall (`min`).
  + Jumlah maksimum milidetik yang dihabiskan di remoteCall (`max`).
+ Total waktu yang dikonsumsi oleh RemoteCalls to ElasticSearch ()`remoteCallTime`.
+ Jumlah RemoteCalls dibuat untuk ElasticSearch ()`remoteCalls`.
+ Jumlah milidetik yang dihabiskan dalam gabungan ElasticSearch hasil ()`joinTime`.
+ Jumlah milidetik yang dihabiskan dalam pencarian indeks (`indexTime`).
+ Jumlah total hasil yang dikembalikan oleh ElasticSearch (`remoteResults`).

# Dukungan langkah Gremlin asli di Amazon Neptune
<a name="gremlin-step-support"></a>

Mesin Amazon Neptune saat ini tidak memiliki dukungan asli penuh untuk semua langkah Gremlin, seperti yang dijelaskan di [Menyetel kueri Gremlin](gremlin-traversal-tuning.md). Dukungan saat ini terbagi dalam empat kategori:
+ [Langkah-langkah Gremlin yang selalu dapat dikonversi ke operasi mesin Neptune asli](#gremlin-steps-always)
+ [Langkah Gremlin yang dapat dikonversi ke operasi mesin Neptune asli dalam beberapa kasus](#gremlin-steps-sometimes) 
+ [Langkah Gremlin yang tidak pernah dikonversi ke operasi mesin Neptune asli](#gremlin-steps-never) 
+ [Langkah-langkah Gremlin yang tidak didukung di Neptune sama sekali](#neptune-gremlin-steps-unsupported) 

## Langkah-langkah Gremlin yang selalu dapat dikonversi ke operasi mesin Neptune asli
<a name="gremlin-steps-always"></a>

Banyak langkah Gremlin dapat dikonversi ke operasi mesin Neptune asli selama mereka memenuhi kondisi berikut:
+ Mereka tidak didahului di dalam kueri dengan langkah yang tidak dapat dikonversi.
+ Langkah induk mereka, jika ada, dapat dikonversi,
+ Semua traversals turunan mereka, jika ada, dapat dikonversi.

Langkah-langkah Gremlin berikut selalu dikonversi ke operasi mesin Neptune asli jika mereka memenuhi kondisi tersebut:
+ [dan](http://tinkerpop.apache.org/docs/current/reference/#and-step)
+ [sebagai ()](http://tinkerpop.apache.org/docs/current/reference/#as-step)
+ [menghitung ()](http://tinkerpop.apache.org/docs/current/reference/#count-step)
+ [E ()](http://tinkerpop.apache.org/docs/current/reference/#graph-step)
+ [memancarkan ()](http://tinkerpop.apache.org/docs/current/reference/#emit-step)
+ [menjelaskan ()](http://tinkerpop.apache.org/docs/current/reference/#explain-step)
+ [kelompok ()](http://tinkerpop.apache.org/docs/current/reference/#group-step)
+ [GroupCount ()](http://tinkerpop.apache.org/docs/current/reference/#groupcount-step)
+ [identitas ()](http://tinkerpop.apache.org/docs/current/reference/#identity-step)
+ [adalah](http://tinkerpop.apache.org/docs/current/reference/#is-step)
+ [kunci ()](http://tinkerpop.apache.org/docs/current/reference/#key-step)
+ [label ()](http://tinkerpop.apache.org/docs/current/reference/#label-step)
+ [batas ()](http://tinkerpop.apache.org/docs/current/reference/#limit-step)
+ [lokal ()](http://tinkerpop.apache.org/docs/current/reference/#local-step)
+ [loop ()](http://tinkerpop.apache.org/docs/current/reference/#loops-step)
+ [tidak ()](http://tinkerpop.apache.org/docs/current/reference/#not-step)
+ [atau ()](http://tinkerpop.apache.org/docs/current/reference/#or-step)
+ [profil ()](http://tinkerpop.apache.org/docs/current/reference/#profile-step)
+ [properti ()](http://tinkerpop.apache.org/docs/current/reference/#properties-step)
+ [subgraf ()](http://tinkerpop.apache.org/docs/current/reference/#subgraph-step)
+ [sampai ()](http://tinkerpop.apache.org/docs/current/reference/#until-step)
+ [V ()](http://tinkerpop.apache.org/docs/current/reference/#graph-step)
+ [nilai ()](http://tinkerpop.apache.org/docs/current/reference/#value-step)
+ [ValueMap ()](http://tinkerpop.apache.org/docs/current/reference/#valuemap-step)
+ [nilai ()](http://tinkerpop.apache.org/docs/current/reference/#values-step)

## Langkah Gremlin yang dapat dikonversi ke operasi mesin Neptune asli dalam beberapa kasus
<a name="gremlin-steps-sometimes"></a>

Beberapa langkah Gremlin dapat dikonversi ke operasi mesin Neptune asli dalam beberapa situasi tetapi tidak pada situasi lain:
+ [addE( )](http://tinkerpop.apache.org/docs/current/reference/#addedge-step) — Langkah `addE()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali segera diikuti oleh langkah `property()` yang berisi traversal sebagai kunci.
+ [addV( )](http://tinkerpop.apache.org/docs/current/reference/#addvertex-step) — Langkah `addV()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali segera diikuti oleh langkah `property()` yang berisi traversal sebagai kunci, atau kecuali beberapa label ditetapkan.
+ [aggregate( )](http://tinkerpop.apache.org/docs/current/reference/#store-step) — Langkah `aggregate()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali langkah ini digunakan dalam traversal turunan atau sub-traversal, atau kecuali nilai yang disimpan adalah sesuatu selain vertex, edge, id, label atau nilai properti.

  Dalam contoh di bawah ini, `aggregate()` tidak dikonversi karena sedang digunakan dalam traversal turunan:

  ```
  g.V().has('code','ANC').as('a')
       .project('flights').by(select('a')
       .outE().aggregate('x'))
  ```

  Dalam contoh ini, aggregate( ) tidak dikonversi karena yang disimpan adalah `min()` dari nilai:

  ```
  g.V().has('code','ANC').outE().aggregate('x').by(values('dist').min())
  ```
+ [barrier( )](http://tinkerpop.apache.org/docs/current/reference/#barrier-step) — Langkah `barrier()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali langkah yang mengikutinya tidak dikonversi.
+ [cap( )](http://tinkerpop.apache.org/docs/current/reference/#cap-step) — Satu-satunya kasus di mana langkah `cap()` dikonversi adalah ketika dikombinasikan dengan langkah `unfold()` untuk mengembalikan versi tidak dilipat dari agregat vertex, edge, id, atau nilai poperti. Dalam contoh ini, `cap()` akan dikonversi karena diikuti oleh `.unfold()`:

  ```
  g.V().has('airport','country','IE').aggregate('airport').limit(2)
       .cap('airport').unfold()
  ```

  Namun, jika Anda menghapus `.unfold()`, `cap()` tidak akan dikonversi:

  ```
  g.V().has('airport','country','IE').aggregate('airport').limit(2)
       .cap('airport')
  ```
+ [coalesce ()](http://tinkerpop.apache.org/docs/current/reference/#coalesce-step) [— Satu-satunya kasus di mana `coalesce()` langkah dikonversi adalah ketika mengikuti [pola Upsert](http://tinkerpop.apache.org/docs/current/recipes/#element-existence) yang direkomendasikan pada halaman resep. TinkerPop ](http://tinkerpop.apache.org/docs/current/recipes/) Pola coalesce( ) lainnya tidak diperbolehkan. Konversi terbatas pada kasus di mana semua traversals turunan dapat dikonversi, mereka semua menghasilkan jenis yang sama sebagai output (vertex, edge, id, nilai, kunci, atau label), mereka semua melakukan traversal ke elemen baru, dan mereka tidak mengandung langkah `repeat()`.
+ [constant( )](http://tinkerpop.apache.org/docs/current/reference/#constant-step) — Langkah constant( ) saat ini hanya dikonversi jika digunakan dalam bagian `sack().by()` dari traversal untuk menetapkan nilai konstan, seperti ini:

  ```
  g.V().has('code','ANC').sack(assign).by(constant(10)).out().limit(2)
  ```
+ [cyclicPath( )](http://tinkerpop.apache.org/docs/current/reference/#cyclicpath-step) — Langkah `cyclicPath()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali langkah ini digunakan dengan modulator `by()`, `from()`, atau `to()`. Dalam kueri berikut, misalnya, `cyclicPath()` tidak dikonversi:

  ```
  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) — Langkah `drop()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali langkah ini digunakan di dalam langkah `sideEffect(` atau `optional()`.
+ [fold ()](http://tinkerpop.apache.org/docs/current/reference/#fold-step) — Hanya ada dua situasi di mana langkah fold () dapat dikonversi, yaitu ketika digunakan dalam [pola Upsert](http://tinkerpop.apache.org/docs/current/recipes/#element-existence) yang direkomendasikan pada [halaman TinkerPop resep](http://tinkerpop.apache.org/docs/current/recipes/), dan ketika digunakan dalam `group().by()` konteks seperti ini:

  ```
  g.V().has('code','ANC').out().group().by().by(values('code', 'city').fold())
  ```
+  [has ()](http://tinkerpop.apache.org/docs/current/reference/#has-step) — Langkah `has () `umumnya dapat dikonversi ke operasi mesin Neptunus asli yang disediakan kueri dengan `T` menggunakan predikat `P.eq`, `P.neq` atau `P.contains`. Harapkan variasi `has () `yang menyiratkan contoh `P` untuk dikonversi ke native juga, seperti `HasiD ('id1234')` yang setara dengan `has (eq, t.id, 'id1234') `. 
+ [id( )](http://tinkerpop.apache.org/docs/current/reference/#id-step) — Langkah `id()` dikonversi kecuali digunakan pada properti, seperti ini:

  ```
  g.V().has('code','ANC').properties('code').id()
  ```
+  [Mergee ()](https://tinkerpop.apache.org/docs/current/reference/#mergeedge-step) — `mergeE()` Langkah dapat dikonversi ke operasi mesin Neptunus asli jika parameter (kondisi gabungan, `onCreate` dan`onMatch`) konstan (baik, konstanta`null`, atau a). `Map` `select()` `Map` Semua contoh di [tepi atas](https://docs.aws.amazon.com//neptune/latest/userguide/gremlin-efficient-upserts.html#gremlin-upserts-edges) dapat dikonversi. 
+  [MergeV ()](https://tinkerpop.apache.org/docs/current/reference/#mergevertex-step) — Langkah mergeV () dapat dikonversi ke operasi mesin Neptunus asli jika parameter (kondisi gabungan, `onCreate` dan`onMatch`) konstan (baik, konstanta, atau `null` a). `Map` `select()` `Map` Semua contoh dalam [simpul upserting dapat dikonversi.](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) — Langkah `order()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali langkah yang mengikutinya adalah true:
  + Langkah `order()` berada dalam traversal turunan nested, seperti ini:

    ```
    g.V().has('code','ANC').where(V().out().order().by(id))
    ```
  + Pengurutan lokal sedang digunakan, seperti misalnya dengan `order(local)`.
  + Sebuah pembanding kustom sedang digunakan dalam modulasi `by()` untuk mengurutkan. Contohnya adalah penggunaan `sack()` ini:

    ```
    g.withSack(0).
      V().has('code','ANC').
          repeat(outE().sack(sum).by('dist').inV()).times(2).limit(10).
          order().by(sack())
    ```
  + Ada beberapa pengurutan pada elemen yang sama.
+ [project( )](http://tinkerpop.apache.org/docs/current/reference/#project-step) — Langkah `project()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali jumlah pernyataan `by()` yang mengikuti `project()` tidak cocok dengan jumlah label yang ditentukan, seperti di sini:

  ```
  g.V().has('code','ANC').project('x', 'y').by(id)
  ```
+ [range( )](http://tinkerpop.apache.org/docs/current/reference/#range-step) — Langkah `range()` hanya dikonversi ketika ujung bawah rentang yang dimaksud adalah nol (misalnya, `range(0,3)`).
+ [repeat( )](http://tinkerpop.apache.org/docs/current/reference/#repeat-step) — Langkah `repeat()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali di-nested di dalam langkah `repeat()` lain, seperti ini:

  ```
  g.V().has('code','ANC').repeat(out().repeat(out()).times(2)).times(2)
  ```
+ [sack( )](http://tinkerpop.apache.org/docs/current/reference/#sack-step) — Langkah `sack()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali dalam kasus berikut:
  + Jika operator sack non-numerik sedang digunakan.
  + Jika operator sack numerik selain `+`, `-`, `mult`, `div`, `min` dan `max` sedang digunakan.
  + Jika `sack()` digunakan di dalam langkah `where()` untuk menyaring berdasarkan nilai sack, seperti di sini:

    ```
    g.V().has('code','ANC').sack(assign).by(values('code')).where(sack().is('ANC'))
    ```
+ [sum( )](http://tinkerpop.apache.org/docs/current/reference/#sum-step) — Langkah `sum()` umumnya dapat dikonversi ke operasi mesin Neptune asli, tetapi tidak ketika digunakan untuk menghitung penjumlahan global, seperti ini:

  ```
  g.V().has('code','ANC').outE('routes').values('dist').sum()
  ```
+ [union ()](http://tinkerpop.apache.org/docs/current/reference/#union-step) — `union()` Langkah ini dapat dikonversi ke operasi mesin Neptunus asli selama itu adalah langkah terakhir dalam kueri selain dari langkah terminal.
+ [unfold ()](http://tinkerpop.apache.org/docs/current/reference/#unfold-step) — `unfold()` Langkah ini hanya dapat dikonversi ke operasi mesin Neptunus asli ketika digunakan dalam pola [Upsert yang](http://tinkerpop.apache.org/docs/current/recipes/#element-existence) direkomendasikan pada TinkerPop halaman [resep](http://tinkerpop.apache.org/docs/current/recipes/), dan ketika digunakan bersama dengan seperti ini: `cap()`

  ```
  g.V().has('airport','country','IE').aggregate('airport').limit(2)
       .cap('airport').unfold()
  ```
+ [where( )](http://tinkerpop.apache.org/docs/current/reference/#where-step) — Langkah `where()` umumnya dapat dikonversi ke operasi mesin Neptune asli, kecuali dalam kasus berikut:
  + Saat modulasi by( ) digunakan, seperti ini:

    ```
    g.V().hasLabel('airport').as('a')
         .where(gt('a')).by('runways')
    ```
  + Ketika operator perbandingan selain `eq`, `neq`, `within`, dan `without` digunakan.
  + Ketika agregasi yang disediakan pengguna digunakan.

## Langkah Gremlin yang tidak pernah dikonversi ke operasi mesin Neptune asli
<a name="gremlin-steps-never"></a>

Langkah-langkah Gremlin berikut didukung di Neptune tetapi tidak pernah dikonversi ke operasi mesin Neptune asli. Sebaliknya, mereka dieksekusi oleh server Gremlin.
+ [pilih ()](http://tinkerpop.apache.org/docs/current/reference/#choose-step)
+ [koin ()](http://tinkerpop.apache.org/docs/current/reference/#coin-step)
+ [menyuntikkan ()](http://tinkerpop.apache.org/docs/current/reference/#inject-step)
+ [cocok ()](http://tinkerpop.apache.org/docs/current/reference/#match-step)
+ [matematika ()](http://tinkerpop.apache.org/docs/current/reference/#math-step)
+ [maks ()](http://tinkerpop.apache.org/docs/current/reference/#max-step)
+ [berarti ()](http://tinkerpop.apache.org/docs/current/reference/#mean-step)
+ [min ()](http://tinkerpop.apache.org/docs/current/reference/#min-step)
+ [pilihan ()](http://tinkerpop.apache.org/docs/current/reference/#option-step)
+ [opsional ()](http://tinkerpop.apache.org/docs/current/reference/#optional-step)
+ [jalan ()](http://tinkerpop.apache.org/docs/current/reference/#path-step)
+ [PropertyMap ()](http://tinkerpop.apache.org/docs/current/reference/#propertymap-step)
+ [sampel ()](http://tinkerpop.apache.org/docs/current/reference/#sample-step)
+ [lewati ()](http://tinkerpop.apache.org/docs/current/reference/#skip-step)
+ [ekor ()](http://tinkerpop.apache.org/docs/current/reference/#tail-step)
+ [TimeLimit ()](http://tinkerpop.apache.org/docs/current/reference/#timelimit-step)
+ [pohon ()](http://tinkerpop.apache.org/docs/current/reference/#tree-step)

## Langkah-langkah Gremlin yang tidak didukung di Neptune sama sekali
<a name="neptune-gremlin-steps-unsupported"></a>

Langkah-langkah Gremlin berikut tidak didukung sama sekali di Neptune. Dalam kebanyakan kasus ini karena mereka memerlukan `GraphComputer`, yang saat ini tidak didukung Neptune.
+ [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)
+ [denganKomputer ()](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)

`io()`Langkah ini sebenarnya sebagian didukung, karena dapat digunakan untuk `read()` dari URL tetapi tidak untuk`write()`.

# Menggunakan Gremlin dengan mesin kueri Neptunus DFE
<a name="gremlin-with-dfe"></a>

Jika Anda mengaktifkan [mesin kueri alternatif](neptune-dfe-engine.md) Neptunus yang dikenal sebagai DFE dalam [mode lab](features-lab-mode.md) (dengan menyetel parameter cluster `neptune_lab_mode` DB ke)`DFEQueryEngine=enabled`, maka Neptunus menerjemahkan Gremlin hanya-baca queries/traversals menjadi representasi logis perantara dan menjalankannya pada mesin DFE bila memungkinkan.

Namun, DFE belum mendukung semua langkah Gremlin. Ketika sebuah langkah tidak dapat dijalankan secara asli di DFE, Neptunus kembali menjalankan langkahnya. TinkerPop `profile`Laporan `explain` dan termasuk peringatan ketika ini terjadi.

# Cakupan langkah Gremlin di DFE
<a name="gremlin-step-coverage-in-DFE"></a>

 Gremlin DFE adalah fitur labmode dan dapat digunakan dengan mengaktifkan parameter cluster atau menggunakan petunjuk kueri. `Neptune#useDFE` Untuk informasi lebih lanjut, silakan merujuk ke [Menggunakan Gremlin dengan mesin kueri Neptunus DFE](https://docs.aws.amazon.com//neptune/latest/userguide/gremlin-with-dfe.html). 

 Langkah-langkah berikut tersedia untuk digunakan di Gremlin DFE. 

## Langkah-langkah jalur dan traversal:
<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 (), sample ()](https://tinkerpop.apache.org/docs/current/reference/#sack-step)[, [select ()](https://tinkerpop.apache.org/docs/current/reference/#select-step)](https://tinkerpop.apache.org/docs/current/reference/#sample-step), [sideEffect ()](https://tinkerpop.apache.org/docs/current/reference/#sideeffect-step), [split ()](https://tinkerpop.apache.org/docs/current/reference/#split-step), [unfold (), union ()](https://tinkerpop.apache.org/docs/current/reference/#unfold-step)](https://tinkerpop.apache.org/docs/current/reference/#union-step) 

## Langkah-langkah agregat dan pengumpulan:
<a name="DFE-aggregate-and-collection"></a>

 [agregat (global)](https://tinkerpop.apache.org/docs/current/reference/#aggregate-step), [gabungkan ()](https://tinkerpop.apache.org/docs/current/reference/#combine-step), [hitung ()](https://tinkerpop.apache.org/docs/current/reference/#count-step), [dedup ()](https://tinkerpop.apache.org/docs/current/reference/#dedup-step), [dedup (lokal), lipat ()](https://tinkerpop.apache.org/docs/current/reference/#dedup-step)[, grup ()](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), 

## Langkah-langkah matematika:
<a name="DFE-mathematical"></a>

 [max ()](https://tinkerpop.apache.org/docs/current/reference/#max-step), [mean ()](https://tinkerpop.apache.org/docs/current/reference/#mean-step), [min ()](https://tinkerpop.apache.org/docs/current/reference/#min-step), [sum ()](https://tinkerpop.apache.org/docs/current/reference/#sum-step) 

## Langkah-langkah elemen:
<a name="DFE-element"></a>

 [otherV ()](https://tinkerpop.apache.org/docs/current/reference/#otherv-step), [elementMap (), elemen ()](https://tinkerpop.apache.org/docs/current/reference/#elementmap-step)[, v ()](https://tinkerpop.apache.org/docs/current/reference/#element-step)[, out ()](https://tinkerpop.apache.org/docs/current/reference/#graph-step)[, in (), keduanya (), oute (), inE (), boThe (), outV (), inV (), bothV (), otherV ()](https://tinkerpop.apache.org/docs/current/reference/#vertex-step) 

## Langkah-langkah properti:
<a name="DFE-property"></a>

 [properti ()](https://tinkerpop.apache.org/docs/current/reference/#properties-step), [key ()](https://tinkerpop.apache.org/docs/current/reference/#key-step), [valueMap ()](https://tinkerpop.apache.org/docs/current/reference/#propertymap-step), [value](https://tinkerpop.apache.org/docs/current/reference/#value-step) () 

## Langkah-langkah filter:
<a name="DFE-filter"></a>

 [dan ()](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 (), none ()](https://tinkerpop.apache.org/docs/current/reference/#local-step)[, not ()](https://tinkerpop.apache.org/docs/current/reference/#none-step)[, or ()](https://tinkerpop.apache.org/docs/current/reference/#not-step)[, where ()](https://tinkerpop.apache.org/docs/current/reference/#or-step)](https://tinkerpop.apache.org/docs/current/reference/#where-step) 

## Langkah-langkah manipulasi string:
<a name="DFE-string-manipulation"></a>

 [concat ()](https://tinkerpop.apache.org/docs/current/reference/#concat-step)[, [lTrim ()](https://tinkerpop.apache.org/docs/current/reference/#lTrim-step), [rTrim (), substring ()](https://tinkerpop.apache.org/docs/current/reference/#rtrim-step)[, toLower (),](https://tinkerpop.apache.org/docs/current/reference/#substring-step)[[toupper](https://tinkerpop.apache.org/docs/current/reference/#toUpper-step) ()](https://tinkerpop.apache.org/docs/current/reference/#toLower-step), trim ()](https://tinkerpop.apache.org/docs/current/reference/#trim-step) 

## Predikat:
<a name="DFE-predicates"></a>
+  [Bandingkan: eq, neq, lt, lte, gt, gte](https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates) 
+  [Berisi: di dalam, tanpa](https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates) 
+  [TextP: EndingWith, berisi,,, NotContaining notStartingWith notEndingWith](https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates) 
+  [P: dan, atau, antara, di luar, di dalam](https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates) 

## Batasan
<a name="gremlin-with-dfe-limitations"></a>

 Ulangi dengan Batas, Label di dalam traversal berulang dan dedup belum didukung di 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'))
```

 Jalur dengan pengulangan bersarang, atau langkah percabangan belum didukung. 

```
// 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')
```

## Perencanaan kueri interleaving
<a name="gremlin-with-dfe-interleaving"></a>

Ketika proses penerjemahan menemukan langkah Gremlin yang tidak memiliki operator DFE asli yang sesuai, sebelum kembali menggunakan Tinkerpop, ia mencoba menemukan bagian kueri perantara lainnya yang dapat dijalankan secara asli di mesin DFE. Ini dilakukan dengan menerapkan logika interleaving ke traversal tingkat atas. Hasilnya adalah langkah-langkah yang didukung digunakan sedapat mungkin.

Terjemahan kueri non-awalan menengah seperti itu direpresentasikan menggunakan `NeptuneInterleavingStep` dalam `explain` dan `profile` output.

Untuk perbandingan kinerja, Anda mungkin ingin mematikan interleaving dalam kueri, sambil tetap menggunakan mesin DFE untuk menjalankan bagian awalan. Atau, Anda mungkin hanya ingin menggunakan TinkerPop mesin untuk eksekusi kueri non-awalan. Anda dapat melakukan ini dengan menggunakan petunjuk `disableInterleaving` kueri.

Sama seperti petunjuk [useDFE](gremlin-query-hints-useDFE.md) kueri dengan nilai `false` mencegah kueri dijalankan di DFE sama sekali, petunjuk `disableInterleaving` kueri dengan nilai `true` mematikan interleaving DFE untuk terjemahan kueri. Contoh:

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

## Diperbarui Gremlin `explain` dan output `profile`
<a name="gremlin-with-dfe-explain-update"></a>

Gremlin [menjelaskan](gremlin-explain.md) memberikan rincian tentang traversal yang dioptimalkan yang digunakan Neptunus untuk menjalankan kueri. Lihat [contoh `explain` keluaran DFE](gremlin-explain-api.md#gremlin-explain-dfe) untuk contoh seperti apa `explain` output saat mesin DFE diaktifkan.

[API `profile` Gremlin](gremlin-profile-api.md)Menjalankan traversal Gremlin tertentu, mengumpulkan berbagai metrik tentang proses, dan menghasilkan laporan profil yang berisi detail tentang rencana kueri yang dioptimalkan dan statistik runtime dari berbagai operator. Lihat [contoh `profile` keluaran DFE](gremlin-profile-api.md#gremlin-profile-sample-dfe-output) untuk contoh seperti apa `profile` output saat mesin DFE diaktifkan.

**catatan**  
Karena mesin DFE adalah fitur eksperimental yang dirilis dalam mode lab, format `explain` dan `profile` output yang tepat dapat berubah.

# Mengakses Grafik Neptunus dengan OpenCypher
<a name="access-graph-opencypher"></a>

Neptunus mendukung pembuatan aplikasi grafik menggunakan OpenCypher, saat ini salah satu bahasa kueri paling populer untuk pengembang yang bekerja dengan database grafik. Pengembang, analis bisnis, dan ilmuwan data menyukai sintaks yang terinspirasi SQL OpenCypher karena menyediakan struktur yang akrab untuk menyusun kueri untuk aplikasi grafik.

**OpenCypher** [adalah bahasa query deklaratif untuk grafik properti yang awalnya dikembangkan oleh Neo4j, kemudian open-source pada tahun 2015, dan berkontribusi pada proyek OpenCypher di bawah lisensi open-source Apache 2.](http://www.opencypher.org/) Sintaksnya didokumentasikan dalam [Referensi Bahasa Kueri Cypher, Versi 9](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf).

Untuk keterbatasan dan perbedaan dukungan Neptunus dari spesifikasi OpenCypher, lihat. [Kepatuhan spesifikasi OpenCypher di Amazon Neptunus](feature-opencypher-compliance.md)

**catatan**  
Implementasi Neo4j saat ini dari bahasa kueri Cypher telah menyimpang dalam beberapa hal dari spesifikasi OpenCypher. Jika Anda memigrasikan kode Neo4j Cypher saat ini ke Neptunus, lihat dan untuk bantuan. [Kompatibilitas Neptunus dengan Neo4j](migration-compatibility.md) [Menulis ulang kueri Cypher untuk dijalankan di OpenCypher di Neptunus](migration-opencypher-rewrites.md)

Dimulai dengan rilis mesin 1.1.1.0, OpenCypher tersedia untuk penggunaan produksi di Neptunus.

## Gremlin vs OpenCypher: persamaan dan perbedaan
<a name="access-graph-opencypher-overview-with-gremlin"></a>

Gremlin dan OpenCypher keduanya adalah bahasa kueri grafik properti, dan keduanya saling melengkapi dalam banyak hal.

Gremlin dirancang untuk menarik programmer dan cocok dengan kode. Akibatnya, Gremlin sangat penting oleh desain, sedangkan sintaks deklaratif OpenCypher mungkin terasa lebih akrab bagi orang-orang dengan pengalaman SQL atau SPARQL. Gremlin mungkin tampak lebih alami bagi ilmuwan data yang menggunakan Python di notebook Jupyter, sedangkan OpenCypher mungkin tampak lebih intuitif bagi pengguna bisnis dengan beberapa latar belakang SQL.

Yang menyenangkan adalah **Anda tidak harus memilih** antara Gremlin dan OpenCypher di Neptunus. Kueri dalam salah satu bahasa dapat beroperasi pada grafik yang sama terlepas dari mana dari dua bahasa yang digunakan untuk memasukkan data tersebut. Anda mungkin merasa lebih nyaman menggunakan Gremlin untuk beberapa hal dan OpenCypher untuk orang lain, tergantung pada apa yang Anda lakukan.

Gremlin menggunakan sintaks imperatif yang memungkinkan Anda mengontrol bagaimana Anda bergerak melalui grafik Anda dalam serangkaian langkah, yang masing-masing mengambil aliran data, melakukan beberapa tindakan di atasnya (menggunakan filter, peta, dan sebagainya), dan kemudian output hasilnya ke langkah berikutnya. Kueri Gremlin biasanya mengambil formulir`g.V()`, diikuti dengan langkah-langkah tambahan.

Di OpenCypher, Anda menggunakan sintaks deklaratif, terinspirasi oleh SQL, yang menentukan pola node dan hubungan untuk ditemukan dalam grafik Anda menggunakan sintaks motif (seperti). `()-[]->()` Query OpenCypher sering dimulai dengan `MATCH` klausa, diikuti oleh klausa lain seperti,, dan. `WHERE` `WITH` `RETURN`

# Memulai menggunakan OpenCypher
<a name="access-graph-opencypher-overview-getting-started"></a>

Anda dapat menanyakan data grafik properti di Neptunus menggunakan OpenCypher terlepas dari bagaimana itu dimuat, tetapi Anda tidak dapat menggunakan OpenCypher untuk menanyakan data yang dimuat sebagai RDF.

[Pemuat [massal Neptunus](bulk-load.md) menerima data grafik properti dalam format CSV untuk Gremlin, dan dalam [format CSV untuk](bulk-load-tutorial-format-gremlin.md) OpenCypher.](bulk-load-tutorial-format-opencypher.md) Juga, tentu saja, Anda dapat menambahkan data properti ke grafik Anda menggunakan kueri Gremlin and/or OpenCypher.

Ada banyak tutorial online yang tersedia untuk mempelajari bahasa query Cypher. [Di sini, beberapa contoh cepat kueri OpenCypher dapat membantu Anda mendapatkan gambaran tentang bahasa tersebut, tetapi sejauh ini cara terbaik dan termudah untuk mulai menggunakan OpenCypher untuk menanyakan grafik Neptunus Anda adalah dengan menggunakan notebook OpenCypher di meja kerja Neptunus.](graph-notebooks.md) Meja kerja adalah sumber terbuka, dan di-host di GitHub . [https://github.com/aws-samples/amazon-neptune-samples](https://github.com/aws-samples/amazon-neptune-samples/)

[Anda akan menemukan notebook OpenCypher di repositori grafik-notebook GitHub Neptunus.](https://github.com/aws/graph-notebook/tree/main/src/graph_notebook/notebooks) Secara khusus, lihat [visualisasi rute Udara](https://github.com/aws/graph-notebook/blob/main/src/graph_notebook/notebooks/02-Visualization/Air-Routes-openCypher.ipynb), dan notebook [Tim Premier Inggris](https://github.com/aws/graph-notebook/blob/main/src/graph_notebook/notebooks/02-Visualization/EPL-openCypher.ipynb) untuk OpenCypher.

Data yang diproses oleh OpenCypher mengambil bentuk serangkaian peta yang tidak teratur. key/value Cara utama untuk memperbaiki, memanipulasi, dan menambah peta ini adalah dengan menggunakan klausa yang melakukan tugas-tugas seperti pencocokan pola, penyisipan, pembaruan, dan penghapusan pada pasangan. key/value 

Ada beberapa klausa di OpenCypher untuk menemukan pola data dalam grafik, yang `MATCH` paling umum. `MATCH`memungkinkan Anda menentukan pola node, hubungan, dan filter yang ingin Anda cari dalam grafik Anda. Contoh:
+ **Dapatkan semua node**

  ```
  MATCH (n) RETURN n
  ```
+ **Temukan node yang terhubung**

  ```
  MATCH (n)-[r]->(d) RETURN n, r, d
  ```
+ **Temukan jalan**

  ```
  MATCH p=(n)-[r]->(d) RETURN p
  ```
+ **Dapatkan semua node dengan label**

  ```
  MATCH (n:airport) RETURN n
  ```

Perhatikan bahwa kueri pertama di atas mengembalikan setiap node dalam grafik Anda, dan dua berikutnya mengembalikan setiap node yang memiliki hubungan — ini umumnya tidak disarankan\$1 Di hampir semua kasus, Anda ingin mempersempit data yang dikembalikan, yang dapat Anda lakukan dengan menentukan label dan properti node atau hubungan, seperti pada contoh keempat.

[Anda dapat menemukan lembar contekan praktis untuk sintaks OpenCypher di repositori sampel github Neptunus.](https://github.com/aws-samples/amazon-neptune-samples/tree/master/opencypher/Cheatsheet.md)

# Servlet status Neptunus OpenCypher dan titik akhir status
<a name="access-graph-opencypher-status"></a>

Titik akhir status OpenCypher menyediakan akses ke informasi tentang kueri yang saat ini berjalan di server atau menunggu untuk dijalankan. Ini juga memungkinkan Anda membatalkan kueri tersebut. Titik akhir adalah:

```
https://(the server):(the port number)/openCypher/status
```

Anda dapat menggunakan HTTP `GET` dan `POST` metode untuk mendapatkan status saat ini dari server, atau untuk membatalkan kueri. Anda juga dapat menggunakan `DELETE` metode ini untuk membatalkan kueri yang sedang berjalan atau menunggu.

## Parameter untuk permintaan status
<a name="access-graph-opencypher-status-parameters"></a>

**Parameter kueri status**
+ **`includeWaiting`**(`true`atau`false`) — Ketika disetel ke `true` dan parameter lain tidak ada, menyebabkan informasi status untuk permintaan menunggu dikembalikan serta untuk menjalankan kueri.
+ **`cancelQuery`**— Digunakan hanya dengan `GET` dan `POST` metode, untuk menunjukkan bahwa ini adalah permintaan pembatalan. `DELETE`Metode ini tidak memerlukan parameter ini.

  Nilai `cancelQuery` parameter tidak digunakan, tetapi ketika `cancelQuery` ada, `queryId` parameter diperlukan, untuk mengidentifikasi kueri mana yang akan dibatalkan.
+ **`queryId`**— Berisi ID dari kueri tertentu.

  Ketika digunakan dengan `POST` metode `GET` or dan `cancelQuery` parameter tidak ada, `queryId` menyebabkan informasi status dikembalikan untuk kueri spesifik yang diidentifikasi. Jika `cancelQuery` parameter ada, maka kueri spesifik yang `queryId` mengidentifikasi dibatalkan.

  Saat digunakan dengan `DELETE` metode ini, `queryId` selalu menunjukkan kueri tertentu yang akan dibatalkan.
+ **`silent`**— Hanya digunakan saat membatalkan kueri. Jika diatur ke`true`, menyebabkan pembatalan terjadi secara diam-diam.

## Bidang respons permintaan status
<a name="access-graph-opencypher-status-response-fields"></a>

**Bidang respons status jika ID kueri tertentu tidak disediakan**
+ **acceptedQueryCount**— Jumlah kueri yang telah diterima tetapi belum selesai, termasuk kueri dalam antrian.
+ **runningQueryCount**— Jumlah kueri OpenCypher yang sedang berjalan.
+ **query** — Daftar query OpenCypher saat ini.

**Bidang respons status untuk kueri tertentu**
+ **queryId** — id GUID untuk kueri. Neptune secara otomatis memberikan nilai ID ini ke setiap kueri, atau Anda juga dapat menetapkan ID Anda sendiri (lihat [Menyuntikkan ID Kustom Ke Dalam Gremlin Neptune atau Kueri SPARQL](features-query-id.md)).
+ **queryString** — Query yang dikirimkan. Ini dipotong menjadi 1024 karakter jika lebih panjang dari itu.
+ **queryEvalStats**— Statistik untuk kueri ini:
  + **menunggu** - Menunjukkan berapa lama kueri menunggu, dalam milidetik.
  + **elapsed** — Jumlah milidetik kueri telah berjalan sejauh ini.
  + **dibatalkan** — `True` menunjukkan bahwa kueri dibatalkan, atau `False` belum dibatalkan.

## Contoh permintaan dan tanggapan status
<a name="access-graph-opencypher-status-samples"></a>
+ **Permintaan status semua pertanyaan, termasuk yang menunggu:**

  ```
  curl https://server:port/openCypher/status \
    --data-urlencode "includeWaiting=true"
  ```

  *Tanggapan:*

  ```
  {
    "acceptedQueryCount" : 0,
    "runningQueryCount" : 0,
    "queries" : [ ]
  }
  ```
+ **Permintaan status kueri yang sedang berjalan, **tidak** termasuk yang menunggu::**

  ```
  curl https://server:port/openCypher/status
  ```

  *Tanggapan:*

  ```
  {
    "acceptedQueryCount" : 0,
    "runningQueryCount" : 0,
    "queries" : [ ]
  }
  ```
+ **Permintaan status kueri tunggal:**

  ```
  curl https://server:port/openCypher/status \
   --data-urlencode "queryId=eadc6eea-698b-4a2f-8554-5270ab17ebee"
  ```

  *Tanggapan:*

  ```
  {
    "queryId" : "eadc6eea-698b-4a2f-8554-5270ab17ebee",
    "queryString" : "MATCH (n1)-[:knows]->(n2), (n2)-[:knows]->(n3), (n3)-[:knows]->(n4), (n4)-[:knows]->(n5), (n5)-[:knows]->(n6), (n6)-[:knows]->(n7), (n7)-[:knows]->(n8), (n8)-[:knows]->(n9), (n9)-[:knows]->(n10) RETURN COUNT(n1);",
    "queryEvalStats" : {
      "waited" : 0,
      "elapsed" : 23463,
      "cancelled" : false
    }
  }
  ```
+ **Permintaan untuk membatalkan kueri**

  1. Menggunakan`POST` :

  ```
  curl -X POST https://server:port/openCypher/status \
    --data-urlencode "cancelQuery" \
    --data-urlencode "queryId=f43ce17b-db01-4d37-a074-c76d1c26d7a9"
  ```

  *Tanggapan:*

  ```
  {
    "status" : "200 OK",
    "payload" : true
  }
  ```

  2. Menggunakan`GET` :

  ```
  curl -X GET https://server:port/openCypher/status \
    --data-urlencode "cancelQuery" \
    --data-urlencode "queryId=588af350-cfde-4222-bee6-b9cedc87180d"
  ```

  *Tanggapan:*

  ```
  {
    "status" : "200 OK",
    "payload" : true
  }
  ```

  3. Menggunakan`DELETE` :

  ```
  curl -X DELETE \
    -s "https://server:port/openCypher/status?queryId=b9a516d1-d25c-4301-bb80-10b2743ecf0e"
  ```

  *Tanggapan:*

  ```
  {
    "status" : "200 OK",
    "payload" : true
  }
  ```

# Titik akhir HTTPS Amazon OpenCypher Neptunus
<a name="access-graph-opencypher-queries"></a>

**Topics**
+ [OpenCypher membaca dan menulis kueri pada titik akhir HTTPS](#access-graph-opencypher-queries-read-write)
+ [Format hasil OpenCypher JSON default](#access-graph-opencypher-queries-results-simple-JSON)
+ [Header tambahan HTTP opsional untuk respons multi-bagian OpenCypher](#optional-http-trailing-headers)

**catatan**  
Neptunus saat ini tidak mendukung HTTP/2 untuk permintaan REST API. Klien harus menggunakan HTTP/1.1 saat menghubungkan ke titik akhir.

## OpenCypher membaca dan menulis kueri pada titik akhir HTTPS
<a name="access-graph-opencypher-queries-read-write"></a>

Titik akhir OpenCypher HTTPS mendukung kueri baca dan pembaruan menggunakan metode `GET` dan metode. `POST` `PUT`Metode `DELETE` dan tidak didukung.

Instruksi berikut memandu Anda melalui koneksi ke OpenCypher titik akhir menggunakan `curl` perintah dan HTTPS. Anda harus mengikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

Sintaksnya adalah:

```
HTTPS://(the server):(the port number)/openCypher
```

Berikut adalah contoh kueri baca, yang menggunakan `POST` dan yang menggunakan`GET`:

1. Menggunakan`POST` :

```
curl HTTPS://server:port/openCypher \
  -d "query=MATCH (n1) RETURN n1;"
```

2. Menggunakan `GET` (string kueri dikodekan URL):

```
curl -X GET \
  "HTTPS://server:port/openCypher?query=MATCH%20(n1)%20RETURN%20n1"
```

Berikut adalah contoh write/update kueri, salah satu yang menggunakan `POST` dan satu yang menggunakan`GET`:

1. Menggunakan`POST` :

```
curl HTTPS://server:port/openCypher \
  -d "query=CREATE (n:Person { age: 25 })"
```

2. Menggunakan `GET` (string kueri dikodekan URL):

```
curl -X GET \
  "HTTPS://server:port/openCypher?query=CREATE%20(n%3APerson%20%7B%20age%3A%2025%20%7D)"
```

## Format hasil OpenCypher JSON default
<a name="access-graph-opencypher-queries-results-simple-JSON"></a>

Format JSON berikut dikembalikan secara default, atau dengan mengatur header permintaan secara eksplisit ke. `Accept: application/json` Format ini dirancang agar mudah diurai menjadi objek menggunakan fitur bahasa asli dari sebagian besar perpustakaan.

Dokumen JSON yang dikembalikan berisi satu bidang`results`, yang berisi nilai pengembalian kueri. Contoh di bawah ini menunjukkan pemformatan JSON untuk nilai-nilai umum.

**Contoh respons nilai:**

```
{
  "results": [
    {
      "count(a)": 121
    }
  ]
}
```

**Contoh respons simpul:**

```
{
  "results": [
    {
      "a": {
        "~id": "22",
        "~entityType": "node",
        "~labels": [
          "airport"
        ],
        "~properties": {
          "desc": "Seattle-Tacoma",
          "lon": -122.30899810791,
          "runways": 3,
          "type": "airport",
          "country": "US",
          "region": "US-WA",
          "lat": 47.4490013122559,
          "elev": 432,
          "city": "Seattle",
          "icao": "KSEA",
          "code": "SEA",
          "longest": 11901
        }
      }
    }
  ]
}
```

**Contoh respons hubungan:**

```
{
  "results": [
    {
      "r": {
        "~id": "7389",
        "~entityType": "relationship",
        "~start": "22",
        "~end": "151",
        "~type": "route",
        "~properties": {
          "dist": 956
        }
      }
    }
  ]
}
```

**Contoh respons jalur:**

```
{
  "results": [
    {
      "p": [
        {
          "~id": "22",
          "~entityType": "node",
          "~labels": [
            "airport"
          ],
          "~properties": {
            "desc": "Seattle-Tacoma",
            "lon": -122.30899810791,
            "runways": 3,
            "type": "airport",
            "country": "US",
            "region": "US-WA",
            "lat": 47.4490013122559,
            "elev": 432,
            "city": "Seattle",
            "icao": "KSEA",
            "code": "SEA",
            "longest": 11901
          }
        },
        {
          "~id": "7389",
          "~entityType": "relationship",
          "~start": "22",
          "~end": "151",
          "~type": "route",
          "~properties": {
            "dist": 956
          }
        },
        {
          "~id": "151",
          "~entityType": "node",
          "~labels": [
            "airport"
          ],
          "~properties": {
            "desc": "Ontario International Airport",
            "lon": -117.600997924805,
            "runways": 2,
            "type": "airport",
            "country": "US",
            "region": "US-CA",
            "lat": 34.0559997558594,
            "elev": 944,
            "city": "Ontario",
            "icao": "KONT",
            "code": "ONT",
            "longest": 12198
          }
        }
      ]
    }
  ]
}
```

## Header tambahan HTTP opsional untuk respons multi-bagian OpenCypher
<a name="optional-http-trailing-headers"></a>

 [Fitur ini tersedia dimulai dengan rilis mesin Neptunus 1.4.5.0.](https://docs.aws.amazon.com/releases/release-1.4.5.0.xml) 

 Respons HTTP terhadap OpenCypher kueri dan pembaruan biasanya dikembalikan dalam beberapa potongan. Ketika kegagalan terjadi setelah potongan respons awal dikirim (dengan kode status HTTP 200), mungkin sulit untuk mendiagnosis masalah. Secara default, `Neptunus melaporkan kegagalan tersebut dengan menambahkan pesan kesalahan ke badan pesan, yang mungkin rusak karena sifat streaming dari respons. 

**Menggunakan header trailing**  
 Untuk meningkatkan deteksi dan diagnosis kesalahan, Anda dapat mengaktifkan header trailing dengan menyertakan header trailer transfer-encoding (TE) (te: trailer) dalam permintaan Anda. Melakukan hal ini akan menyebabkan Neptune menyertakan dua bidang header baru dalam header trailing dari potongan respons: 
+  `X-Neptune-Status`— berisi kode respons diikuti dengan nama pendek. Misalnya, dalam kasus keberhasilan, header trailing akan berupa: `X-Neptune-Status: 200 OK`. Dalam kasus kegagalan, kode respons akan menjadi kode kesalahan mesin Neptunus seperti. `X-Neptune-Status: 500 TimeLimitExceededException` 
+  `X-Neptune-Detail`— kosong untuk permintaan yang berhasil. Dalam kasus kesalahan, ia berisi pesan kesalahan JSON. Karena hanya karakter ASCII yang diperbolehkan dalam nilai header HTTP, string JSON di-enkode dengan URL. Pesan kesalahan juga masih ditambahkan ke badan pesan respons. 

 Untuk informasi selengkapnya, lihat [halaman MDN tentang header permintaan TE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/TE). 

**OpenCypher contoh penggunaan header trailing**  
 Contoh ini menunjukkan bagaimana header trailing membantu mendiagnosis kueri yang melebihi batas waktunya: 

```
curl --raw 'https://your-neptune-endpoint:port/openCypher' \
-H 'TE: trailers' \
-d 'query=MATCH(n) RETURN n.firstName'
 
 
Output:
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< trailer: X-Neptune-Status, X-Neptune-Detail
< content-type: application/json;charset=UTF-8
< 
< 
{
  "results": [{
      "n.firstName": "Hossein"
    }, {
      "n.firstName": "Jan"
    }, {
      "n.firstName": "Miguel"
    }, {
      "n.firstName": "Eric"
    }, 
{"detailedMessage":"Operation terminated (deadline exceeded)",
"code":"TimeLimitExceededException",
"requestId":"a7e9d2aa-fbb7-486e-8447-2ef2a8544080",
"message":"Operation terminated (deadline exceeded)"}
0
X-Neptune-Status: 500 TimeLimitExceededException
X-Neptune-Detail: %7B%22detailedMessage%22%3A%22Operation+terminated+%28deadline+exceeded%29%22%2C%22code%22%3A%22TimeLimitExceededException%22%2C%22requestId%22%3A%22a7e9d2aa-fbb7-486e-8447-2ef2a8544080%22%2C%22message%22%3A%22Operation+terminated+%28deadline+exceeded%29%22%7D
```

**Rincian respons:**  
 Contoh sebelumnya menunjukkan bagaimana OpenCypher respons dengan header tambahan dapat membantu mendiagnosis kegagalan kueri. Di sini kita melihat empat bagian berurutan: (1) header awal dengan status 200 OK yang menunjukkan streaming dimulai, (2) hasil JSON sebagian (rusak) berhasil dialirkan sebelum kegagalan, (3) pesan kesalahan yang ditambahkan yang menunjukkan batas waktu, dan (4) header trailing yang berisi status akhir (500) dan informasi kesalahan terperinci. TimeLimitExceededException 

# Menggunakan AWS SDK untuk menjalankan kueri OpenCypher
<a name="access-graph-opencypher-sdk"></a>

Dengan AWS SDK, Anda dapat menjalankan kueri OpenCypher terhadap grafik Neptunus Anda menggunakan bahasa pemrograman pilihan Anda. Neptunus data API SDK (`neptunedata`nama layanan) menyediakan tindakan untuk mengirimkan kueri [ExecuteOpenCypherQuery](https://docs.aws.amazon.com/neptune/latest/data-api/API_ExecuteOpenCypherQuery.html)OpenCypher.

Anda harus menjalankan contoh ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama dengan cluster DB Neptunus Anda, atau dari lokasi yang memiliki konektivitas jaringan ke titik akhir cluster Anda.

Tautan langsung ke dokumentasi referensi API untuk `neptunedata` layanan di setiap bahasa SDK dapat ditemukan di bawah ini:


| Bahasa pemrograman | referensi 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) | 
| Karat | [https://crates.io/crates/aws-sdk-neptunedata](https://crates.io/crates/aws-sdk-neptunedata) | 
| CLI | [https://docs.aws.amazon.com/cli/latest/reference/neptunedata/](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/) | 

## Contoh SDK OpenCypher AWS
<a name="access-graph-opencypher-sdk-examples"></a>

Contoh berikut menunjukkan cara menyiapkan `neptunedata` klien, menjalankan kueri OpenCypher, dan mencetak hasilnya. Ganti *YOUR\$1NEPTUNE\$1HOST* dan *YOUR\$1NEPTUNE\$1PORT* dengan titik akhir dan port cluster DB Neptunus Anda.

**Konfigurasi batas waktu sisi klien dan coba lagi**  
Batas waktu klien SDK mengontrol berapa lama *klien* menunggu respons. Itu tidak mengontrol berapa lama kueri berjalan di server. Jika waktu klien habis sebelum server selesai, kueri dapat terus berjalan di Neptunus sementara klien tidak memiliki cara untuk mengambil hasilnya.  
Sebaiknya atur batas waktu baca sisi klien ke `0` (tanpa batas waktu) atau ke nilai yang setidaknya beberapa detik lebih lama dari pengaturan neptune\$1query\$1timeout sisi server di cluster DB [Neptunus](parameters.md#parameters-db-cluster-parameters-neptune_query_timeout) Anda. Ini memungkinkan Neptunus mengontrol saat waktu kueri habis.  
Kami juga merekomendasikan pengaturan upaya coba ulang maksimum ke `1` (tidak ada percobaan ulang). Jika SDK mencoba ulang kueri yang masih berjalan di server, itu dapat menghasilkan operasi duplikat. Ini sangat penting untuk kueri mutasi, di mana percobaan lagi dapat menyebabkan duplikat penulisan yang tidak diinginkan.

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

1. 4. Ikuti [instruksi instalasi](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) untuk menginstal Boto3.

1. Buat file bernama `openCypherExample.py` dan tempel kode berikut:

   ```
   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})
   )
   
   response = client.execute_open_cypher_query(
       openCypherQuery='MATCH (n) RETURN n LIMIT 1'
   )
   
   print(json.dumps(response['results'], indent=2))
   ```

1. Jalankan contoh: `python openCypherExample.py`

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

1. Ikuti [petunjuk penginstalan](https://docs.aws.amazon.com//sdk-for-java/latest/developer-guide/setup.html) untuk menyiapkan AWS SDK for Java.

1. Gunakan kode berikut untuk menyiapkan`NeptunedataClient`, menjalankan kueri OpenCypher, dan mencetak hasilnya:

   ```
   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.ExecuteOpenCypherQueryRequest;
   import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherQueryResponse;
   
   // 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();
   
   ExecuteOpenCypherQueryRequest request = ExecuteOpenCypherQueryRequest.builder()
       .openCypherQuery("MATCH (n) RETURN n LIMIT 1")
       .build();
   
   ExecuteOpenCypherQueryResponse response = client.executeOpenCypherQuery(request);
   
   System.out.println(response.results().toString());
   ```

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

1. Ikuti [petunjuk penginstalan](https://docs.aws.amazon.com//sdk-for-javascript/v3/developer-guide/getting-started-nodejs.html) untuk menyiapkan AWS SDK. JavaScript Instal paket klien neptunedata:. `npm install @aws-sdk/client-neptunedata`

1. Buat file bernama `openCypherExample.js` dan tempel kode berikut:

   ```
   import { NeptunedataClient, ExecuteOpenCypherQueryCommand } 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);
   
   const input = {
       openCypherQuery: "MATCH (n) RETURN n LIMIT 1"
   };
   
   const command = new ExecuteOpenCypherQueryCommand(input);
   const response = await client.send(command);
   
   console.log(JSON.stringify(response, null, 2));
   ```

1. Jalankan contoh: `node openCypherExample.js`

------

# Menggunakan protokol Bolt untuk membuat kueri OpenCypher ke Neptunus
<a name="access-graph-opencypher-bolt"></a>

[Bolt](https://boltprotocol.org/) [adalah client/server protokol berorientasi pernyataan yang awalnya dikembangkan oleh Neo4j dan dilisensikan di bawah lisensi Creative Commons 3.0 Attribution-. ShareAlike](https://creativecommons.org/licenses/by-sa/3.0/) Ini didorong oleh klien, artinya klien selalu memulai pertukaran pesan.

Untuk terhubung ke Neptunus menggunakan driver Bolt Neo4j, cukup ganti URL dan nomor Port dengan titik akhir cluster Anda menggunakan skema URI. `bolt` Jika Anda memiliki satu instance Neptunus yang berjalan, gunakan endpoint read\$1write. Jika beberapa instance berjalan, maka dua driver direkomendasikan, satu untuk penulis dan satu lagi untuk semua replika baca. Jika Anda hanya memiliki dua titik akhir default, driver read\$1write dan read\$1only sudah cukup, tetapi jika Anda memiliki titik akhir khusus juga, pertimbangkan untuk membuat instance driver untuk masing-masing titik akhir.

**catatan**  
Meskipun spesifikasi Bolt menyatakan bahwa Bolt dapat terhubung menggunakan TCP atau, WebSockets Neptunus hanya mendukung koneksi TCP untuk Bolt.

Neptunus memungkinkan hingga 1000 koneksi Bolt bersamaan pada semua ukuran instans kecuali untuk t3.medium dan t4g.medium. Pada instans t3.medium dan t4g.medium hanya 512 koneksi yang diizinkan.

[Untuk contoh kueri OpenCypher dalam berbagai bahasa yang menggunakan driver Bolt, lihat dokumentasi Neo4j Drivers & Language Guides.](https://neo4j.com/developer/language-guides/)

**penting**  
Driver Neo4j Bolt untuk Python, .NET JavaScript, dan Golang awalnya tidak mendukung pembaruan otomatis token otentikasi Signature v4. AWS Ini berarti bahwa setelah tanda tangan kedaluwarsa (seringkali dalam 5 menit), pengemudi gagal mengautentikasi, dan permintaan berikutnya gagal. Contoh Python, .NET JavaScript, dan Go di bawah ini semuanya terpengaruh oleh masalah ini.  
[Lihat masalah driver [Python Neo4j \$1834, masalah Neo4j .NET \$1664, masalah driver](https://github.com/neo4j/neo4j-python-driver/issues/834)[Neo4j \$1993, dan masalah JavaScript](https://github.com/neo4j/neo4j-dotnet-driver/issues/664)[driver Neo4j GoLang \$1429](https://github.com/neo4j/neo4j-javascript-driver/issues/993) untuk informasi lebih lanjut.](https://github.com/neo4j/neo4j-go-driver/issues/429)  
Pada driver versi 5.8.0, API otentikasi ulang pratinjau baru dirilis untuk driver Go (lihat [v5.8.0](https://github.com/neo4j/neo4j-go-driver/discussions/482) - Umpan balik diinginkan pada otentikasi ulang).

## Menggunakan Bolt dengan Java untuk terhubung ke Neptunus
<a name="access-graph-opencypher-bolt-java"></a>

Anda dapat mengunduh driver untuk versi apa pun yang ingin Anda gunakan dari [repositori Maven MVN](https://mvnrepository.com/artifact/org.neo4j.driver/neo4j-java-driver), atau dapat menambahkan ketergantungan ini ke proyek Anda:

```
<dependency>
  <groupId>org.neo4j.driver</groupId>
  <artifactId>neo4j-java-driver</artifactId>
  <version>4.3.3</version>
</dependency>
```

Kemudian, untuk terhubung ke Neptunus di Jawa menggunakan salah satu driver Bolt ini, buat instance driver untuk instance primary/writer di cluster Anda menggunakan kode seperti berikut:

```
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;

final Driver driver =
  GraphDatabase.driver("bolt://(your cluster endpoint URL):(your cluster port)",
    AuthTokens.none(),
    Config.builder().withEncryption()
                    .withTrustStrategy(TrustStrategy.trustSystemCertificates())
                    .build());
```

Jika Anda memiliki satu atau lebih replika pembaca, Anda juga dapat membuat instance driver untuk mereka menggunakan kode seperti ini:

```
final Driver read_only_driver =              // (without connection timeout)
  GraphDatabase.driver("bolt://(your cluster endpoint URL):(your cluster port)",
      Config.builder().withEncryption()
                      .withTrustStrategy(TrustStrategy.trustSystemCertificates())
                      .build());
```

Atau, dengan batas waktu:

```
final Driver read_only_timeout_driver =      // (with connection timeout)
  GraphDatabase.driver("bolt://(your cluster endpoint URL):(your cluster port)",
    Config.builder().withConnectionTimeout(30, TimeUnit.SECONDS)
                    .withEncryption()
                    .withTrustStrategy(TrustStrategy.trustSystemCertificates())
                    .build());
```

Jika Anda memiliki titik akhir khusus, mungkin juga bermanfaat untuk membuat instance driver untuk masing-masing titik.

## Contoh kueri Python OpenCypher menggunakan Bolt
<a name="access-graph-opencypher-bolt-python"></a>

Berikut adalah cara membuat query OpenCypher dengan Python menggunakan Bolt:

```
python -m pip install neo4j
```

```
from neo4j import GraphDatabase
uri = "bolt://(your cluster endpoint URL):(your cluster port)"
driver = GraphDatabase.driver(uri, auth=("username", "password"), encrypted=True)
```

Perhatikan bahwa `auth` parameter diabaikan.

## Contoh kueri.NET OpenCypher menggunakan Bolt
<a name="access-graph-opencypher-bolt-dotnet"></a>

Untuk membuat kueri OpenCypher di.NET menggunakan Bolt, langkah pertama adalah menginstal driver Neo4j menggunakan. NuHet Untuk melakukan panggilan sinkron, gunakan `.Simple` versi, seperti ini:

```
Install-Package Neo4j.Driver.Simple-4.3.0
```

```
using Neo4j.Driver;

namespace hello
{
  // This example creates a node and reads a node in a Neptune
  // Cluster where IAM Authentication is not enabled.
  public class HelloWorldExample : IDisposable
  {
    private bool _disposed = false;
    private readonly IDriver _driver;
    private static string url = "bolt://(your cluster endpoint URL):(your cluster port)";
    private static string createNodeQuery = "CREATE (a:Greeting) SET a.message = 'HelloWorldExample'";
    private static string readNodeQuery = "MATCH(n:Greeting) RETURN n.message";

    ~HelloWorldExample() => Dispose(false);

    public HelloWorldExample(string uri)
    {
      _driver = GraphDatabase.Driver(uri, AuthTokens.None, o => o.WithEncryptionLevel(EncryptionLevel.Encrypted));
    }

    public void createNode()
    {
      // Open a session
      using (var session = _driver.Session())
      {
         // Run the query in a write transaction
        var greeting = session.WriteTransaction(tx =>
        {
          var result = tx.Run(createNodeQuery);
          // Consume the result
          return result.Consume();
        });

        // The output will look like this:
        //   ResultSummary{Query=`CREATE (a:Greeting) SET a.message = 'HelloWorldExample".....
        Console.WriteLine(greeting);
      }
    }

    public void retrieveNode()
    {
      // Open a session
      using (var session = _driver.Session())
      {
        // Run the query in a read transaction
        var greeting = session.ReadTransaction(tx =>
        {
          var result = tx.Run(readNodeQuery);
          // Consume the result. Read the single node
          // created in a previous step.
          return result.Single()[0].As<string>();
        });
        // The output will look like this:
        //   HelloWorldExample
        Console.WriteLine(greeting);
      }
    }

    public void Dispose()
    {
      Dispose(true);
      GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
      if (_disposed)
        return;
      if (disposing)
      {
        _driver?.Dispose();
      }
      _disposed = true;
    }

    public static void Main()
    {
      using (var apiCaller = new HelloWorldExample(url))
      {
        apiCaller.createNode();
        apiCaller.retrieveNode();
      }
    }
  }
}
```

## Contoh kueri Java OpenCypher menggunakan Bolt dengan otentikasi IAM
<a name="access-graph-opencypher-bolt-java-iam-auth"></a>

Kode Java di bawah ini menunjukkan cara membuat query OpenCypher di Java menggunakan Bolt dengan otentikasi IAM. JavaDoc Komentar tersebut menjelaskan penggunaannya. Setelah instance driver tersedia, Anda dapat menggunakannya untuk membuat beberapa permintaan yang diautentikasi.

```
package software.amazon.neptune.bolt;

import com.amazonaws.DefaultRequest;
import com.amazonaws.Request;
import com.amazonaws.auth.AWS4Signer;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.http.HttpMethodName;
import com.google.gson.Gson;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
import org.neo4j.driver.Value;
import org.neo4j.driver.Values;
import org.neo4j.driver.internal.security.InternalAuthToken;
import org.neo4j.driver.internal.value.StringValue;

import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static com.amazonaws.auth.internal.SignerConstants.AUTHORIZATION;
import static com.amazonaws.auth.internal.SignerConstants.HOST;
import static com.amazonaws.auth.internal.SignerConstants.X_AMZ_DATE;
import static com.amazonaws.auth.internal.SignerConstants.X_AMZ_SECURITY_TOKEN;

/**
 * Use this class instead of `AuthTokens.basic` when working with an IAM
 * auth-enabled server. It works the same as `AuthTokens.basic` when using
 * static credentials, and avoids making requests with an expired signature
 * when using temporary credentials. Internally, it generates a new signature
 * on every invocation (this may change in a future implementation).
 *
 * Note that authentication happens only the first time for a pooled connection.
 *
 * Typical usage:
 *
 * NeptuneAuthToken authToken = NeptuneAuthToken.builder()
 *     .credentialsProvider(credentialsProvider)
 *     .region("aws region")
 *     .url("cluster endpoint url")
 *     .build();
 *
 * Driver driver = GraphDatabase.driver(
 *     authToken.getUrl(),
 *     authToken,
 *     config
 * );
 */

public class NeptuneAuthToken extends InternalAuthToken {
  private static final String SCHEME = "basic";
  private static final String REALM = "realm";
  private static final String SERVICE_NAME = "neptune-db";
  private static final String HTTP_METHOD_HDR = "HttpMethod";
  private static final String DUMMY_USERNAME = "username";
  @NonNull
  private final String region;
  @NonNull
  @Getter
  private final String url;
  @NonNull
  private final AWSCredentialsProvider credentialsProvider;
  private final Gson gson = new Gson();

  @Builder
  private NeptuneAuthToken(
      @NonNull final String region,
      @NonNull final String url,
      @NonNull final AWSCredentialsProvider credentialsProvider
  ) {
      // The superclass caches the result of toMap(), which we don't want
      super(Collections.emptyMap());
      this.region = region;
      this.url = url;
      this.credentialsProvider = credentialsProvider;
  }

  @Override
  public Map<String, Value> toMap() {
    final Map<String, Value> map = new HashMap<>();
    map.put(SCHEME_KEY, Values.value(SCHEME));
    map.put(PRINCIPAL_KEY, Values.value(DUMMY_USERNAME));
    map.put(CREDENTIALS_KEY, new StringValue(getSignedHeader()));
    map.put(REALM_KEY, Values.value(REALM));

    return map;
  }

  private String getSignedHeader() {
    final Request<Void> request = new DefaultRequest<>(SERVICE_NAME);
    request.setHttpMethod(HttpMethodName.GET);
    request.setEndpoint(URI.create(url));
    // Comment out the following line if you're using an engine version older than 1.2.0.0
    request.setResourcePath("/opencypher");

    final AWS4Signer signer = new AWS4Signer();
    signer.setRegionName(region);
    signer.setServiceName(request.getServiceName());
    signer.sign(request, credentialsProvider.getCredentials());

    return getAuthInfoJson(request);
  }

  private String getAuthInfoJson(final Request<Void> request) {
    final Map<String, Object> obj = new HashMap<>();
    obj.put(AUTHORIZATION, request.getHeaders().get(AUTHORIZATION));
    obj.put(HTTP_METHOD_HDR, request.getHttpMethod());
    obj.put(X_AMZ_DATE, request.getHeaders().get(X_AMZ_DATE));
    obj.put(HOST, request.getHeaders().get(HOST));
    obj.put(X_AMZ_SECURITY_TOKEN, request.getHeaders().get(X_AMZ_SECURITY_TOKEN));

    return gson.toJson(obj);
  }
}
```

## Contoh kueri OpenCypher Python menggunakan Bolt dengan otentikasi IAM
<a name="access-graph-opencypher-bolt-python-iam-auth"></a>

Kelas Python di bawah ini memungkinkan Anda membuat kueri OpenCypher dengan Python menggunakan Bolt dengan otentikasi IAM:

```
import json

from neo4j import Auth
from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials
from botocore.auth import (
  SigV4Auth,
  _host_from_url,
)

SCHEME = "basic"
REALM = "realm"
SERVICE_NAME = "neptune-db"
DUMMY_USERNAME = "username"
HTTP_METHOD_HDR = "HttpMethod"
HTTP_METHOD = "GET"
AUTHORIZATION = "Authorization"
X_AMZ_DATE = "X-Amz-Date"
X_AMZ_SECURITY_TOKEN = "X-Amz-Security-Token"
HOST = "Host"


class NeptuneAuthToken(Auth):
  def __init__(
    self,
    credentials: Credentials,
    region: str,
    url: str,
    **parameters
  ):
    # Do NOT add "/opencypher" in the line below if you're using an engine version older than 1.2.0.0
    request = AWSRequest(method=HTTP_METHOD, url=url + "/opencypher")
    request.headers.add_header("Host", _host_from_url(request.url))
    sigv4 = SigV4Auth(credentials, SERVICE_NAME, region)
    sigv4.add_auth(request)

    auth_obj = {
      hdr: request.headers[hdr]
      for hdr in [AUTHORIZATION, X_AMZ_DATE, X_AMZ_SECURITY_TOKEN, HOST]
    }
    auth_obj[HTTP_METHOD_HDR] = request.method
    creds: str = json.dumps(auth_obj)
    super().__init__(SCHEME, DUMMY_USERNAME, creds, REALM, **parameters)
```

Anda menggunakan kelas ini untuk membuat driver sebagai berikut:

```
  authToken = NeptuneAuthToken(creds, REGION, URL)
  driver = GraphDatabase.driver(URL, auth=authToken, encrypted=True)
```

## Contoh Node.js menggunakan otentikasi IAM dan Bolt
<a name="access-graph-opencypher-bolt-nodejs-iam-auth"></a>

Kode Node.js di bawah ini menggunakan AWS SDK untuk JavaScript versi 3 dan ES6 sintaks untuk membuat driver yang mengautentikasi permintaan:

```
import neo4j from "neo4j-driver";
import { HttpRequest }  from "@smithy/protocol-http";
import { defaultProvider } from "@aws-sdk/credential-provider-node";
import { SignatureV4 } from "@smithy/signature-v4";
import crypto from "@aws-crypto/sha256-js";
const { Sha256 } = crypto;
import assert from "node:assert";

const region = "us-west-2";
const serviceName = "neptune-db";
const host = "(your cluster endpoint URL)";
const port = 8182;
const protocol = "bolt";
const hostPort = host + ":" + port;
const url = protocol + "://" + hostPort;
const createQuery = "CREATE (n:Greeting {message: 'Hello'}) RETURN ID(n)";
const readQuery = "MATCH(n:Greeting) WHERE ID(n) = $id RETURN n.message";

async function signedHeader() {
  const req = new HttpRequest({
    method: "GET",
    protocol: protocol,
    hostname: host,
    port: port,
    // Comment out the following line if you're using an engine version older than 1.2.0.0
    path: "/opencypher",
    headers: {
      host: hostPort
    }
  });

  const signer = new SignatureV4({
    credentials: defaultProvider(),
    region: region,
    service: serviceName,
    sha256: Sha256
  });

  return signer.sign(req, { unsignableHeaders: new Set(["x-amz-content-sha256"]) })
    .then((signedRequest) => {
      const authInfo = {
        "Authorization": signedRequest.headers["authorization"],
        "HttpMethod": signedRequest.method,
        "X-Amz-Date": signedRequest.headers["x-amz-date"],
        "Host": signedRequest.headers["host"],
        "X-Amz-Security-Token": signedRequest.headers["x-amz-security-token"]
      };
      return JSON.stringify(authInfo);
    });
}

async function createDriver() {
  let authToken = { scheme: "basic", realm: "realm", principal: "username", credentials: await signedHeader() };

  return neo4j.driver(url, authToken, {
      encrypted: "ENCRYPTION_ON",
      trust: "TRUST_SYSTEM_CA_SIGNED_CERTIFICATES",
      maxConnectionPoolSize: 1,
      // logging: neo4j.logging.console("debug")
    }
  );
}

async function unmanagedTxn(driver) {
  const session = driver.session();
  const tx = session.beginTransaction();
  try {
    const created = await tx.run(createQuery);
    const matched = await tx.run(readQuery, { id: created.records[0].get(0) });
    const msg = matched.records[0].get("n.message");
    assert.equal(msg, "Hello");
    await tx.commit();
  } catch (err) {
    // The transaction will be rolled back, now handle the error.
    console.log(err);
  } finally {
    await session.close();
  }
}

const driver = await createDriver();
try {
  await unmanagedTxn(driver);
} catch (err) {
  console.log(err);
} finally {
  await driver.close();
}
```

## Contoh kueri.NET OpenCypher menggunakan Bolt dengan otentikasi IAM
<a name="access-graph-opencypher-bolt-dotnet-iam-auth"></a>

Untuk mengaktifkan otentikasi IAM di .NET, Anda perlu menandatangani permintaan saat membuat koneksi. Contoh di bawah ini menunjukkan cara membuat `NeptuneAuthToken` helper untuk menghasilkan token otentikasi:

```
using Amazon.Runtime;
using Amazon.Util;
using Neo4j.Driver;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Web;

namespace Hello
{
  /*
   * Use this class instead of `AuthTokens.None` when working with an IAM-auth-enabled server.
   *
   * Note that authentication happens only the first time for a pooled connection.
   *
   * Typical usage:
   *
   * var authToken = new NeptuneAuthToken(AccessKey, SecretKey, Region).GetAuthToken(Host);
   * _driver = GraphDatabase.Driver(Url, authToken, o => o.WithEncryptionLevel(EncryptionLevel.Encrypted));
   */

  public class NeptuneAuthToken
  {
    private const string ServiceName = "neptune-db";
    private const string Scheme = "basic";
    private const string Realm = "realm";
    private const string DummyUserName = "username";
    private const string Algorithm = "AWS4-HMAC-SHA256";
    private const string AWSRequest = "aws4_request";

    private readonly string _accessKey;
    private readonly string _secretKey;
    private readonly string _region;

    private readonly string _emptyPayloadHash;

    private readonly SHA256 _sha256;


    public NeptuneAuthToken(string awsKey = null, string secretKey = null, string region = null)
    {
      var awsCredentials = awsKey == null || secretKey == null
        ? FallbackCredentialsFactory.GetCredentials().GetCredentials()
        : null;

      _accessKey = awsKey ?? awsCredentials.AccessKey;
      _secretKey = secretKey ?? awsCredentials.SecretKey;
      _region = region ?? FallbackRegionFactory.GetRegionEndpoint().SystemName; //ex: us-east-1

      _sha256 = SHA256.Create();
      _emptyPayloadHash = Hash(Array.Empty<byte>());
    }

    public IAuthToken GetAuthToken(string url)
    {
      return AuthTokens.Custom(DummyUserName, GetCredentials(url), Realm, Scheme);
    }

    /******************** AWS SIGNING FUNCTIONS *********************/
    private string Hash(byte[] bytesToHash)
    {
      return ToHexString(_sha256.ComputeHash(bytesToHash));
    }

    private static byte[] HmacSHA256(byte[] key, string data)
    {
      return new HMACSHA256(key).ComputeHash(Encoding.UTF8.GetBytes(data));
    }

    private byte[] GetSignatureKey(string dateStamp)
    {
      var kSecret = Encoding.UTF8.GetBytes($"AWS4{_secretKey}");
      var kDate = HmacSHA256(kSecret, dateStamp);
      var kRegion = HmacSHA256(kDate, _region);
      var kService = HmacSHA256(kRegion, ServiceName);
      return HmacSHA256(kService, AWSRequest);
    }

    private static string ToHexString(byte[] array)
    {
      return Convert.ToHexString(array).ToLowerInvariant();
    }

    private string GetCredentials(string url)
    {
      var request = new HttpRequestMessage
      {
        Method = HttpMethod.Get,
        RequestUri = new Uri($"https://{url}/opencypher")
      };

      var signedrequest = Sign(request);

      var headers = new Dictionary<string, object>
      {
        [HeaderKeys.AuthorizationHeader] = signedrequest.Headers.GetValues(HeaderKeys.AuthorizationHeader).FirstOrDefault(),
        ["HttpMethod"] = HttpMethod.Get.ToString(),
        [HeaderKeys.XAmzDateHeader] = signedrequest.Headers.GetValues(HeaderKeys.XAmzDateHeader).FirstOrDefault(),
        // Host should be capitalized, not like in Amazon.Util.HeaderKeys.HostHeader
        ["Host"] = signedrequest.Headers.GetValues(HeaderKeys.HostHeader).FirstOrDefault(),
      };

      return JsonSerializer.Serialize(headers);
    }

    private HttpRequestMessage Sign(HttpRequestMessage request)
    {
      var now = DateTimeOffset.UtcNow;
      var amzdate = now.ToString("yyyyMMddTHHmmssZ");
      var datestamp = now.ToString("yyyyMMdd");

      if (request.Headers.Host == null)
      {
        request.Headers.Host = $"{request.RequestUri.Host}:{request.RequestUri.Port}";
      }

      request.Headers.Add(HeaderKeys.XAmzDateHeader, amzdate);

      var canonicalQueryParams = GetCanonicalQueryParams(request);

      var canonicalRequest = new StringBuilder();
      canonicalRequest.Append(request.Method + "\n");
      canonicalRequest.Append(request.RequestUri.AbsolutePath + "\n");
      canonicalRequest.Append(canonicalQueryParams + "\n");

      var signedHeadersList = new List<string>();
      foreach (var header in request.Headers.OrderBy(a => a.Key.ToLowerInvariant()))
      {
        canonicalRequest.Append(header.Key.ToLowerInvariant());
        canonicalRequest.Append(':');
        canonicalRequest.Append(string.Join(",", header.Value.Select(s => s.Trim())));
        canonicalRequest.Append('\n');
        signedHeadersList.Add(header.Key.ToLowerInvariant());
      }
      canonicalRequest.Append('\n');

      var signedHeaders = string.Join(";", signedHeadersList);
      canonicalRequest.Append(signedHeaders + "\n");
      canonicalRequest.Append(_emptyPayloadHash);

      var credentialScope = $"{datestamp}/{_region}/{ServiceName}/{AWSRequest}";
      var stringToSign = $"{Algorithm}\n{amzdate}\n{credentialScope}\n"
        + Hash(Encoding.UTF8.GetBytes(canonicalRequest.ToString()));

      var signing_key = GetSignatureKey(datestamp);
      var signature = ToHexString(HmacSHA256(signing_key, stringToSign));

      request.Headers.TryAddWithoutValidation(HeaderKeys.AuthorizationHeader,
        $"{Algorithm} Credential={_accessKey}/{credentialScope}, SignedHeaders={signedHeaders}, Signature={signature}");

      return request;
    }

    private static string GetCanonicalQueryParams(HttpRequestMessage request)
    {
      var querystring = HttpUtility.ParseQueryString(request.RequestUri.Query);

      // Query params must be escaped in upper case (i.e. "%2C", not "%2c").
      var queryParams = querystring.AllKeys.OrderBy(a => a)
        .Select(key => $"{key}={Uri.EscapeDataString(querystring[key])}");
      return string.Join("&", queryParams);
    }
  }
}
```

Berikut adalah cara membuat query OpenCypher di.NET menggunakan Bolt dengan otentikasi IAM. Contoh di bawah ini menggunakan `NeptuneAuthToken` helper:

```
using Neo4j.Driver;

namespace Hello
{
  public class HelloWorldExample
  {
    private const string Host = "(your hostname):8182";
    private const string Url = $"bolt://{Host}";
    private const string CreateNodeQuery = "CREATE (a:Greeting) SET a.message = 'HelloWorldExample'";
    private const string ReadNodeQuery = "MATCH(n:Greeting) RETURN n.message";

    private const string AccessKey = "(your access key)";
    private const string SecretKey = "(your secret key)";
    private const string Region = "(your AWS region)"; // e.g. "us-west-2"

    private readonly IDriver _driver;

    public HelloWorldExample()
    {
      var authToken = new NeptuneAuthToken(AccessKey, SecretKey, Region).GetAuthToken(Host);

      // Note that when the connection is reinitialized after max connection lifetime
      // has been reached, the signature token could have already been expired (usually 5 min)
      // You can face exceptions like:
      //   `Unexpected server exception 'Signature expired: XXXX is now earlier than YYYY (ZZZZ - 5 min.)`
      _driver = GraphDatabase.Driver(Url, authToken, o =>
                o.WithMaxConnectionLifetime(TimeSpan.FromMinutes(60)).WithEncryptionLevel(EncryptionLevel.Encrypted));
    }

    public async Task CreateNode()
    {
      // Open a session
      using (var session = _driver.AsyncSession())
      {
        // Run the query in a write transaction
        var greeting = await session.WriteTransactionAsync(async tx =>
        {
          var result = await tx.RunAsync(CreateNodeQuery);
          // Consume the result
          return await result.ConsumeAsync();
        });

        // The output will look like this:
        //   ResultSummary{Query=`CREATE (a:Greeting) SET a.message = 'HelloWorldExample".....
        Console.WriteLine(greeting.Query);
      }
    }

    public async Task RetrieveNode()
    {
      // Open a session
      using (var session = _driver.AsyncSession())
      {
        // Run the query in a read transaction
        var greeting = await session.ReadTransactionAsync(async tx =>
        {
          var result = await tx.RunAsync(ReadNodeQuery);
          var records = await result.ToListAsync();

          // Consume the result. Read the single node
          // created in a previous step.
          return records[0].Values.First().Value;
        });
        // The output will look like this:
        //   HelloWorldExample
        Console.WriteLine(greeting);
      }
    }
  }
}
```

Contoh ini dapat diluncurkan dengan menjalankan kode di bawah ini pada `.NET 6` atau `.NET 7` dengan paket-paket berikut:
+ **`Neo4j`**`.Driver=4.3.0`
+ **`AWSSDK`**`.Core=3.7.102.1`

```
namespace Hello
{
  class Program
  {
    static async Task Main()
    {
      var apiCaller = new HelloWorldExample();

      await apiCaller.CreateNode();
      await apiCaller.RetrieveNode();
    }
  }
}
```

## Contoh kueri Golang OpenCypher menggunakan Bolt dengan otentikasi IAM
<a name="access-graph-opencypher-bolt-golang-iam-auth"></a>

Paket Golang di bawah ini menunjukkan cara membuat kueri OpenCypher dalam bahasa Go menggunakan Bolt dengan otentikasi IAM:

```
package main

import (
  "context"
  "encoding/json"
  "fmt"
  "github.com/aws/aws-sdk-go/aws/credentials"
  "github.com/aws/aws-sdk-go/aws/signer/v4"
  "github.com/neo4j/neo4j-go-driver/v5/neo4j"
  "log"
  "net/http"
  "os"
  "time"
)

const (
  ServiceName   = "neptune-db"
  DummyUsername = "username"
)

// Find node by id using Go driver
func findNode(ctx context.Context, region string, hostAndPort string, nodeId string) (string, error) {
  req, err := http.NewRequest(http.MethodGet, "https://"+hostAndPort+"/opencypher", nil)

  if err != nil {
    return "", fmt.Errorf("error creating request, %v", err)
  }

  // credentials must have been exported as environment variables
  signer := v4.NewSigner(credentials.NewEnvCredentials())
  _, err = signer.Sign(req, nil, ServiceName, region, time.Now())

  if err != nil {
    return "", fmt.Errorf("error signing request: %v", err)
  }

  hdrs := []string{"Authorization", "X-Amz-Date", "X-Amz-Security-Token"}
  hdrMap := make(map[string]string)
  for _, h := range hdrs {
    hdrMap[h] = req.Header.Get(h)
  }

  hdrMap["Host"] = req.Host
  hdrMap["HttpMethod"] = req.Method

  password, err := json.Marshal(hdrMap)
  if err != nil {
    return "", fmt.Errorf("error creating JSON, %v", err)
  }
  authToken := neo4j.BasicAuth(DummyUsername, string(password), "")
  // +s enables encryption with a full certificate check
  // Use +ssc to disable client side TLS verification
  driver, err := neo4j.NewDriverWithContext("bolt+s://"+hostAndPort+"/opencypher", authToken)
  if err != nil {
    return "", fmt.Errorf("error creating driver, %v", err)
  }

  defer driver.Close(ctx)

  if err := driver.VerifyConnectivity(ctx); err != nil {
    log.Fatalf("failed to verify connection, %v", err)
  }

  config := neo4j.SessionConfig{}

  session := driver.NewSession(ctx, config)
  defer session.Close(ctx)

  result, err := session.Run(
    ctx,
    fmt.Sprintf("MATCH (n) WHERE ID(n) = '%s' RETURN n", nodeId),
    map[string]any{},
  )
  if err != nil {
    return "", fmt.Errorf("error running query, %v", err)
  }

  if !result.Next(ctx) {
    return "", fmt.Errorf("node not found")
  }

  n, found := result.Record().Get("n")
  if !found {
    return "", fmt.Errorf("node not found")
  }

  return fmt.Sprintf("+%v\n", n), nil
}

func main() {
  if len(os.Args) < 3 {
    log.Fatal("Usage: go main.go (region) (host and port)")
  }
  region := os.Args[1]
  hostAndPort := os.Args[2]
  ctx := context.Background()

  res, err := findNode(ctx, region, hostAndPort, "72c2e8c1-7d5f-5f30-10ca-9d2bb8c4afbc")
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(res)
}
```

## Perilaku koneksi baut di Neptunus
<a name="access-graph-opencypher-bolt-connections"></a>

Berikut adalah beberapa hal yang perlu diingat tentang koneksi Neptunus Bolt:
+ Karena koneksi Bolt dibuat pada layer TCP, Anda tidak dapat menggunakan [Application Load](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html) Balancer di depannya, seperti yang Anda bisa dengan endpoint HTTP.
+ Port yang digunakan Neptunus untuk koneksi Bolt adalah port cluster DB Anda.
+ Berdasarkan pembukaan Bolt yang diteruskan ke sana, server Neptunus memilih versi Bolt tertinggi yang sesuai (1, 2, 3, atau 4.0).
+ Jumlah maksimum koneksi ke server Neptunus yang dapat dibuka klien kapan saja adalah 1.000.
+ Jika klien tidak menutup koneksi setelah kueri, koneksi itu dapat digunakan untuk menjalankan kueri berikutnya.
+ Namun, jika koneksi menganggur selama 20 menit, server menutupnya secara otomatis.
+ Jika autentikasi IAM tidak diaktifkan, Anda dapat menggunakan `AuthTokens.none()` daripada memasok nama pengguna dan kata sandi dummy. Misalnya, di Jawa:

  ```
  GraphDatabase.driver("bolt://(your cluster endpoint URL):(your cluster port)", AuthTokens.none(),
      Config.builder().withEncryption().withTrustStrategy(TrustStrategy.trustSystemCertificates()).build());
  ```
+ Ketika autentikasi IAM diaktifkan, koneksi Bolt selalu terputus beberapa menit lebih dari 10 hari setelah dibuat jika belum ditutup karena alasan lain.
+ Jika klien mengirim kueri untuk dieksekusi melalui koneksi tanpa menghabiskan hasil kueri sebelumnya, kueri baru akan dibuang. Untuk membuang hasil sebelumnya, klien harus mengirim pesan reset melalui koneksi.
+ Hanya satu transaksi pada satu waktu yang dapat dibuat pada koneksi tertentu.
+ Jika pengecualian terjadi selama transaksi, server Neptunus memutar kembali transaksi dan menutup koneksi. Dalam hal ini, driver membuat koneksi baru untuk kueri berikutnya.
+ Ketahuilah bahwa sesi tidak aman untuk utas. Beberapa operasi parallel harus menggunakan beberapa sesi terpisah.

# Contoh kueri parameter OpenCypher
<a name="opencypher-parameterized-queries"></a>

Neptunus mendukung kueri OpenCypher berparameter. Ini memungkinkan Anda menggunakan struktur kueri yang sama beberapa kali dengan argumen yang berbeda. Karena struktur kueri tidak berubah, Neptunus dapat men-cache pohon sintaks abstrak (AST) daripada harus menguraikannya beberapa kali.

## Contoh kueri parameter OpenCypher menggunakan titik akhir HTTPS
<a name="opencypher-http-parameterized-queries"></a>

Di bawah ini adalah contoh penggunaan kueri parameter dengan titik akhir Neptunus OpenCypher HTTPS. Kuerinya adalah:

```
MATCH (n {name: $name, age: $age})
RETURN n
```

Parameter didefinisikan sebagai berikut:

```
parameters={"name": "john", "age": 20}
```

Dengan menggunakan`GET`, Anda dapat mengirimkan kueri berparameter seperti ini:

```
curl -k \
  "https://localhost:8182/openCypher?query=MATCH%20%28n%20%7Bname:\$name,age:\$age%7D%29%20RETURN%20n&parameters=%7B%22name%22:%22john%22,%22age%22:20%7D"
```

Atau, Anda dapat menggunakan`POST`:

```
curl -k \
  https://localhost:8182/openCypher \
  -d "query=MATCH (n {name: \$name, age: \$age}) RETURN n" \
  -d "parameters={\"name\": \"john\", \"age\": 20}"
```

Atau, menggunakan`DIRECT POST`:

```
curl -k \
   -H "Content-Type: application/opencypher" \
  "https://localhost:8182/openCypher?parameters=%7B%22name%22:%22john%22,%22age%22:20%7D" \
  -d "MATCH (n {name: \$name, age: \$age}) RETURN n"
```

## Contoh kueri parameter OpenCypher menggunakan Bolt
<a name="opencypher-bolt-parameterized-queries"></a>

Berikut adalah contoh Python dari kueri parameter OpenCypher menggunakan protokol Bolt:

```
from neo4j import GraphDatabase
uri = "bolt://[neptune-endpoint-url]:8182"
driver = GraphDatabase.driver(uri, auth=("", ""))

def match_name_and_age(tx, name, age):
  # Parameterized Query
  tx.run("MATCH (n {name: $name, age: $age}) RETURN n", name=name, age=age)

with driver.session() as session:
  # Parameters
  session.read_transaction(match_name_and_age, "john", 20)

driver.close()
```

Berikut adalah contoh Java dari kueri parameter OpenCypher menggunakan protokol Bolt:

```
Driver driver = GraphDatabase.driver("bolt+s://(your cluster endpoint URL):8182");
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("name", "john");
parameters.put("age", 20);
String queryString = "MATCH (n {name: $name, age: $age}) RETURN n";
Result result = driver.session().run(queryString, parameters);
```

# Model data OpenCypher
<a name="access-graph-opencypher-data-model"></a>

Mesin Neptunus OpenCypher dibangun di atas model grafik properti yang sama dengan Gremlin. Khususnya:
+ Setiap node memiliki satu atau lebih label. Jika Anda menyisipkan node tanpa label, label default bernama `vertex` dilampirkan. Jika Anda mencoba menghapus semua label node, kesalahan akan dilemparkan.
+ Hubungan adalah entitas yang memiliki persis satu jenis hubungan dan yang membentuk koneksi searah antara dua node (yaitu, *dari* salah satu node *ke* node lainnya).
+ Baik node dan hubungan dapat memiliki properti, tetapi tidak harus. Neptunus mendukung node dan hubungan dengan properti nol.
+ Neptunus tidak mendukung metaproperties, yang juga tidak termasuk dalam spesifikasi OpenCypher.
+ Properti dalam grafik Anda dapat bernilai banyak jika dibuat menggunakan Gremlin. Itu adalah node atau properti hubungan dapat memiliki satu set nilai yang berbeda daripada hanya satu. Neptunus telah memperluas semantik OpenCypher untuk menangani properti multi-nilai dengan anggun.

Tipe data yang didukung didokumentasikan di[Format data OpenCypher](bulk-load-tutorial-format-opencypher.md). Namun, kami tidak menyarankan memasukkan nilai `Array` properti ke dalam grafik OpenCypher saat ini. Meskipun dimungkinkan untuk memasukkan nilai properti array menggunakan pemuat massal, rilis Neptunus OpenCypher saat ini memperlakukannya sebagai satu set properti multi-nilai alih-alih sebagai nilai daftar tunggal.

Di bawah ini adalah daftar tipe data yang didukung dalam rilis ini:
+ `Bool`
+ `Byte`
+ `Short`
+ `Int` 
+ `Long`
+ `Float`(Termasuk plus dan minus Infinity dan NaN, tapi bukan INF)
+ `Double`(Termasuk plus dan minus Infinity dan NaN, tapi bukan INF)
+ `DateTime` 
+ `String`

# Fitur OpenCypher `explain`
<a name="access-graph-opencypher-explain"></a>

`explain`Fitur OpenCypher adalah alat swalayan di Amazon Neptunus yang membantu Anda memahami pendekatan eksekusi yang diambil oleh mesin Neptunus. Untuk memanggil menjelaskan, Anda meneruskan parameter ke permintaan [HTTPS](access-graph-opencypher-queries.md) OpenCypher dengan`explain=mode`, di mana `mode` nilainya dapat berupa salah satu dari yang berikut:

****
+ **`static`**— Dalam `static` mode, hanya `explain` mencetak struktur statis dari rencana kueri. Itu tidak benar-benar menjalankan kueri.
+ **`dynamic`**— Dalam `dynamic` mode, `explain` juga menjalankan kueri, dan mencakup aspek dinamis dari rencana kueri. Ini mungkin termasuk jumlah binding perantara yang mengalir melalui operator, rasio binding masuk ke binding keluar, dan total waktu yang dibutuhkan oleh masing-masing operator.
+ **`details`**— Dalam `details` mode, `explain` mencetak informasi yang ditampilkan dalam mode dinamis ditambah detail tambahan, seperti string kueri OpenCypher yang sebenarnya dan perkiraan jumlah rentang untuk pola yang mendasari operator gabungan.

  

Misalnya, menggunakan`POST`:

```
curl HTTPS://server:port/openCypher \
  -d "query=MATCH (n) RETURN n LIMIT 1;" \
  -d "explain=dynamic"
```

Atau, menggunakan`GET`:

```
curl -X GET \
  "HTTPS://server:port/openCypher?query=MATCH%20(n)%20RETURN%20n%20LIMIT%201&explain=dynamic"
```

## Keterbatasan untuk `explain` OpenCypher di Neptunus
<a name="access-graph-opencypher-explain-limitations"></a>

Rilis OpenCypher menjelaskan saat ini memiliki batasan berikut:
+ Jelaskan rencana saat ini hanya tersedia untuk kueri yang melakukan operasi hanya-baca. Kueri yang melakukan mutasi apa pun, seperti`CREATE`,, `DELETE``MERGE`, `SET` dan sebagainya, tidak didukung.
+ Operator dan output untuk rencana tertentu dapat berubah dalam rilis future.

## Operator DFE dalam keluaran OpenCypher `explain`
<a name="access-graph-opencypher-dfe-operators"></a>

Untuk menggunakan informasi yang disediakan oleh `explain` fitur OpenCypher, Anda perlu memahami beberapa detail tentang cara kerja [mesin kueri DFE (DFE menjadi mesin](neptune-dfe-engine.md) yang digunakan Neptunus untuk memproses kueri OpenCypher).

Mesin DFE menerjemahkan setiap kueri ke dalam saluran operator. Mulai dari operator pertama, solusi perantara mengalir dari satu operator ke operator berikutnya melalui pipeline operator ini. Setiap baris dalam tabel jelaskan mewakili hasil, hingga titik evaluasi.

Operator yang dapat muncul dalam paket kueri DFE adalah sebagai berikut:

**DFEApply**— Mengeksekusi fungsi yang ditentukan di bagian argumen, pada nilai yang disimpan dalam variabel tertentu

**DFEBindRelasi** - Mengikat variabel dengan nama yang ditentukan

**DFEChunkLocalSubQuery**— Ini adalah operasi non-pemblokiran yang bertindak sebagai pembungkus di sekitar subquery yang sedang dilakukan.

**DFEDistinctKolom** - Mengembalikan subset yang berbeda dari nilai masukan berdasarkan variabel yang ditentukan.

**DFEDistinctRelasi** — Mengembalikan subset yang berbeda dari solusi masukan berdasarkan variabel yang ditentukan.

**DFEDrain**— Muncul di akhir subquery untuk bertindak sebagai langkah penghentian untuk subquery itu. Jumlah solusi dicatat sebagai`Units In`. `Units Out`selalu nol.

**DFEForwardNilai** - Menyalin semua potongan input secara langsung sebagai potongan keluaran untuk diteruskan ke operator hilirnya.

**DFEGroupByHashIndex**— Melakukan operasi kelompok-demi melalui solusi input berdasarkan indeks hash yang dihitung sebelumnya (menggunakan operasi). `DFEHashIndexBuild` Sebagai output, input yang diberikan diperpanjang oleh kolom yang berisi kunci grup untuk setiap solusi masukan.

**DFEHashIndexBuild**— Membangun indeks hash di atas satu set variabel sebagai efek samping. Indeks hash ini biasanya digunakan kembali dalam operasi selanjutnya. Lihat `DFEHashIndexJoin` atau `DFEGroupByHashIndex` di mana indeks hash ini dapat digunakan.

**DFEHashIndexJoin**— Melakukan gabungan atas solusi yang masuk terhadap indeks hash yang dibangun sebelumnya. Lihat `DFEHashIndexBuild` di mana indeks hash ini mungkin dibangun.

**DFEJoinAda** - Mengambil relasi input tangan kiri dan kanan, dan mempertahankan nilai dari relasi kiri yang memiliki nilai yang sesuai dalam relasi kanan seperti yang didefinisikan oleh variabel gabungan yang diberikan. 

****— Ini adalah operasi non-pemblokiran yang bertindak sebagai pembungkus untuk subquery, yang memungkinkannya dijalankan berulang kali untuk digunakan dalam loop.

**DFEMergePotongan** — Ini adalah operasi pemblokiran yang menggabungkan potongan dari operator hulu menjadi satu potongan solusi untuk diteruskan ke operator hilirnya (kebalikan dari). `DFESplitChunks`

**DFEMinus**— Mengambil relasi input tangan kiri dan kanan, dan mempertahankan nilai dari relasi kiri yang tidak memiliki nilai yang sesuai dalam relasi kanan seperti yang didefinisikan oleh variabel gabungan yang diberikan. Jika tidak ada tumpang tindih dalam variabel di kedua relasi, maka operator ini hanya mengembalikan relasi input tangan kiri.

**DFENotAda** - Mengambil relasi input tangan kiri dan kanan, dan mempertahankan nilai dari relasi kiri yang tidak memiliki nilai yang sesuai dalam relasi kanan seperti yang didefinisikan oleh variabel gabungan yang diberikan. Jika tidak ada tumpang tindih dalam variabel di kedua relasi, maka operator ini mengembalikan relasi kosong.

**DFEOptionalGabung** — Melakukan gabungan luar kiri (juga disebut gabungan OPSIONAL): solusi dari sisi kiri yang memiliki setidaknya satu mitra bergabung di sisi kanan digabungkan, dan solusi dari sisi kiri tanpa mitra bergabung di sisi kanan diteruskan apa adanya. Ini adalah operasi pemblokiran.

**DFEPipelineGabung - Bergabung** dengan input terhadap pola Tuple yang ditentukan oleh argumen. `pattern`

**DFEPipelineRangeCount**— Menghitung jumlah solusi yang cocok dengan pola yang diberikan, dan mengembalikan solusi satu-ary tunggal yang berisi nilai hitungan.

**DFEPipelineScan — Memindai** database untuk `pattern` argumen yang diberikan, dengan atau tanpa filter yang diberikan pada kolom (s).

**DFEProject**— Mengambil beberapa kolom input dan proyek hanya kolom yang diinginkan.

**DFEReduce**— Melakukan fungsi agregasi tertentu pada variabel tertentu.

**DFERelationalGabung - Bergabung dengan** masukan dari operator sebelumnya berdasarkan tombol pola yang ditentukan menggunakan gabungan gabungan. Ini adalah operasi pemblokiran.

**DFERoutePotongan - Mengambil potongan** input dari tepi masuk tunggal dan merutekan potongan tersebut di sepanjang beberapa tepi keluarnya.

**DFESelectBaris** — Operator ini secara selektif mengambil baris dari solusi relasi input kirinya untuk diteruskan ke operator hilirnya. Baris yang dipilih berdasarkan pengidentifikasi baris yang disediakan dalam relasi input kanan operator.

**DFESerialize**— Serialisasi hasil akhir kueri menjadi serialisasi string JSON, memetakan setiap solusi input ke nama variabel yang sesuai. Untuk hasil node dan edge, hasil ini diserialisasikan ke dalam peta properti entitas dan metadata.

**DFESort**— Mengambil relasi input dan menghasilkan relasi yang diurutkan berdasarkan kunci sortir yang disediakan.

**DFESplitByGroup**— Membagi setiap potongan input tunggal dari satu tepi masuk menjadi potongan keluaran yang lebih kecil yang sesuai dengan grup baris yang diidentifikasi oleh baris IDs dari potongan input yang sesuai dari tepi masuk lainnya.

**DFESplitPotongan — Membagi setiap potongan** input tunggal menjadi potongan keluaran yang lebih kecil (kebalikan dari). `DFEMergeChunks`

**DFEStreamingHashIndexBuild**— Versi streaming dari`DFEHashIndexBuild`.

**DFEStreamingGroupByHashIndex**— Versi streaming dari`DFEGroupByHashIndex`.

**DFESubquery**— Operator ini muncul di awal semua rencana dan merangkum bagian-bagian dari rencana yang dijalankan pada [mesin DFE](neptune-dfe-engine.md), yang merupakan keseluruhan rencana untuk OpenCypher.

**DFESymmetricHashJoin**— Bergabung dengan masukan dari operator sebelumnya berdasarkan tombol pola yang ditentukan menggunakan gabungan hash. Ini adalah operasi non-pemblokiran.

**DFESync**— Operator ini adalah operator sinkronisasi yang mendukung rencana non-pemblokiran. Dibutuhkan solusi dari dua sisi yang masuk dan meneruskan solusi ini ke tepi hilir yang sesuai. Untuk tujuan sinkronisasi, input di sepanjang salah satu tepi ini dapat disangga secara internal. 

**DFETee**— Ini adalah operator percabangan yang mengirimkan serangkaian solusi yang sama ke beberapa operator.

**DFETermResolusi** — Melakukan operasi lokalisasi atau globalisasi pada inputnya, menghasilkan kolom pengidentifikasi lokal atau global masing-masing.

****— Membuka daftar nilai dari kolom input ke kolom output sebagai elemen individual.

**DFEUnion**— Mengambil dua atau lebih hubungan masukan dan menghasilkan penyatuan relasi-relasi tersebut menggunakan skema output yang diinginkan.

**SolutionInjection**— Muncul sebelum segala sesuatu yang lain dalam output menjelaskan, dengan nilai 1 di kolom Units Out. Namun, ini berfungsi sebagai no-op, dan tidak benar-benar menyuntikkan solusi apa pun ke mesin DFE.

**TermResolution**— Muncul di akhir rencana dan menerjemahkan objek dari mesin Neptunus ke objek OpenCypher.

## Kolom dalam keluaran OpenCypher `explain`
<a name="access-graph-opencypher-explain-columns"></a>

Informasi rencana kueri yang dihasilkan Neptunus sebagai OpenCypher menjelaskan output berisi tabel dengan satu operator per baris. Tabel memiliki kolom berikut:

**ID** — ID numerik operator ini dalam paket.

**Keluar \$11** (dan **Keluar \$12**) — ID operator yang berada di hilir dari operator ini. Paling banyak ada dua operator hilir.

**Nama** — Nama operator ini.

**Argumen** — Setiap detail yang relevan untuk operator. Ini termasuk hal-hal seperti skema input, skema output, pola (untuk `PipelineScan` dan`PipelineJoin`), dan sebagainya.

**Mode** — Label yang menjelaskan perilaku operator mendasar. Kolom ini sebagian besar kosong (`-`). Satu pengecualian adalah`TermResolution`, di mana mode bisa`id2value_opencypher`, menunjukkan resolusi dari ID ke nilai OpenCypher.

**Unit In** — Jumlah solusi yang diteruskan sebagai masukan ke operator ini. Operator tanpa operator hulu, seperti`DFEPipelineScan`,`SolutionInjections`, dan tanpa nilai statis `DFESubquery` yang disuntikkan, akan memiliki nilai nol.

**Unit Keluar** — Jumlah solusi yang dihasilkan sebagai output dari operator ini. `DFEDrain`adalah kasus khusus, di mana jumlah larutan yang dikeringkan dicatat `Units In` dan `Units Out` selalu nol.

**Rasio** — Rasio `Units Out` terhadap`Units In`.

**Waktu (ms)** — Waktu CPU yang dikonsumsi oleh operator ini, dalam milidetik.

## Contoh dasar OpenCypher menjelaskan output
<a name="access-graph-opencypher-explain-basic-example"></a>

Berikut ini adalah contoh dasar dari output OpenCypher`explain`. Kueri adalah pencarian simpul tunggal dalam dataset rute udara untuk node dengan kode bandara `ATL` yang memanggil `explain` menggunakan `details` mode dalam format output ASCII default:

```
curl -d "query=MATCH (n {code: 'ATL'}) RETURN n" -k https://localhost:8182/openCypher -d "explain=details"                                                                                                      ~
Query:
MATCH (n {code: 'ATL'}) RETURN n

╔════╤════════╤════════╤═══════════════════╤════════════════════╤═════════════════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments          │ Mode                │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪════════════════════╪═════════════════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]     │ -                   │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFESubquery       │ subQuery=subQuery1 │ -                   │ 0        │ 1         │ 0.00  │ 4.00      ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ -      │ -      │ TermResolution    │ vars=[?n]          │ id2value_opencypher │ 1        │ 1         │ 1.00  │ 2.00      ║
╚════╧════════╧════════╧═══════════════════╧════════════════════╧═════════════════════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery1
╔════╤════════╤════════╤═══════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                  │ Arguments                                                                                                    │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFEPipelineScan       │ pattern=Node(?n) with property 'code' as ?n_code2 and label 'ALL'                                            │ -    │ 0        │ 1         │ 0.00  │ 0.21      ║
║    │        │        │                       │ inlineFilters=[(?n_code2 IN ["ATL"^^xsd:string])]                                                            │      │          │           │       │           ║
║    │        │        │                       │ patternEstimate=1                                                                                            │      │          │           │       │           ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#9d84f97c-c3b0-459a-98d5-955a8726b159/graph_1 │ -    │ 1        │ 1         │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ DFEProject            │ columns=[?n]                                                                                                 │ -    │ 1        │ 1         │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ -      │ -      │ DFEDrain              │ -                                                                                                            │ -    │ 1        │ 0         │ 0.00  │ 0.03      ║
╚════╧════════╧════════╧═══════════════════════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#9d84f97c-c3b0-459a-98d5-955a8726b159/graph_1
╔════╤════════╤════════╤══════════════════════╤════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                 │ Arguments                                                  │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪══════════════════════╪════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFESolutionInjection │ outSchema=[?n, ?n_code2]                                   │ -    │ 0        │ 1         │ 0.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ 3      │ DFETee               │ -                                                          │ -    │ 1        │ 2         │ 2.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 4      │ -      │ DFEDistinctColumn    │ column=?n                                                  │ -    │ 1        │ 1         │ 1.00  │ 0.20      ║
║    │        │        │                      │ ordered=false                                              │      │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 5      │ -      │ DFEHashIndexBuild    │ vars=[?n]                                                  │ -    │ 1        │ 1         │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ DFEPipelineJoin      │ pattern=Node(?n) with property 'ALL' and label '?n_label1' │ -    │ 1        │ 1         │ 1.00  │ 0.25      ║
║    │        │        │                      │ patternEstimate=3506                                       │      │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ 6      │ 7      │ DFESync              │ -                                                          │ -    │ 2        │ 2         │ 1.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 6  │ 8      │ -      │ DFEForwardValue      │ -                                                          │ -    │ 1        │ 1         │ 1.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 7  │ 8      │ -      │ DFEForwardValue      │ -                                                          │ -    │ 1        │ 1         │ 1.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 8  │ 9      │ -      │ DFEHashIndexJoin     │ -                                                          │ -    │ 2        │ 1         │ 0.50  │ 0.35      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 9  │ -      │ -      │ DFEDrain             │ -                                                          │ -    │ 1        │ 0         │ 0.00  │ 0.02      ║
╚════╧════════╧════════╧══════════════════════╧════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝
```

Di tingkat atas, `SolutionInjection` muncul sebelum yang lainnya, dengan 1 unit keluar. Perhatikan bahwa itu tidak benar-benar menyuntikkan solusi apa pun. Anda dapat melihat bahwa operator berikutnya,`DFESubquery`, memiliki 0 unit.

Setelah `SolutionInjection` di tingkat atas adalah `DFESubquery` dan `TermResolution` operator. `DFESubquery`merangkum bagian-bagian dari rencana eksekusi kueri yang sedang didorong ke [mesin DFE](neptune-dfe-engine.md) (untuk kueri OpenCypher, seluruh rencana kueri dijalankan oleh DFE). Semua operator dalam paket kueri bersarang di dalam `subQuery1` yang direferensikan oleh. `DFESubquery` Satu-satunya pengecualian adalah`TermResolution`, yang terwujud internal IDs menjadi objek OpenCypher yang sepenuhnya diserialisasi.

Semua operator yang didorong ke mesin DFE memiliki nama yang dimulai dengan `DFE` awalan. Seperti disebutkan di atas, seluruh rencana kueri OpenCypher dijalankan oleh DFE, sehingga sebagai hasilnya, semua operator kecuali operator akhir `TermResolution` memulai dengan. `DFE`

Di dalam`subQuery1`, mungkin ada nol atau lebih `DFEChunkLocalSubQuery` atau `DFELoopSubQuery` operator yang merangkum bagian dari rencana eksekusi yang didorong yang dijalankan dalam mekanisme yang dibatasi memori. `DFEChunkLocalSubQuery`di sini berisi salah satu `SolutionInjection` yang digunakan sebagai masukan ke subquery. Untuk menemukan tabel untuk subquery tersebut di output, cari yang `subQuery=graph URI` ditentukan di `Arguments` kolom untuk `DFELoopSubQuery` operator `DFEChunkLocalSubQuery` or.

Dalam`subQuery1`, `DFEPipelineScan` dengan `ID` 0 memindai database untuk yang ditentukan`pattern`. Pola memindai entitas dengan properti yang `code` disimpan sebagai variabel `?n_code2` di atas semua label (Anda dapat memfilter pada label tertentu dengan menambahkan `airport` ke`n:airport`). `inlineFilters`Argumen menunjukkan penyaringan untuk `code` properti yang sama`ATL`.

Selanjutnya, `DFEChunkLocalSubQuery` operator bergabung dengan hasil perantara dari subquery yang berisi. `DFEPipelineJoin` Ini memastikan bahwa sebenarnya `?n` adalah simpul, karena sebelumnya `DFEPipelineScan` memindai entitas apa pun dengan `code` properti.

# Contoh `explain` output untuk pencarian hubungan dengan batas
<a name="access-graph-opencypher-explain-example-2"></a>

Kueri ini mencari hubungan antara dua node anonim dengan tipe`route`, dan mengembalikan paling banyak 10. Sekali lagi, `explain` modenya `details` dan format output adalah format ASCII default. Berikut adalah `explain` outputnya:

Di sini, `DFEPipelineScan` memindai tepi yang dimulai dari simpul anonim `?anon_node7` dan berakhir di simpul anonim lainnya`?anon_node21`, dengan tipe hubungan disimpan sebagai`?p_type1`. Ada filter untuk `?p_type1` being `el://route` (di mana `el` singkatan dari label tepi), yang sesuai dengan `[p:route]` dalam string kueri.

`DFEDrain`mengumpulkan solusi output dengan batas 10, seperti yang ditunjukkan pada `Arguments` kolomnya. `DFEDrain`berakhir setelah batas tercapai atau semua solusi diproduksi, mana yang terjadi lebih dulu.

```
curl -d "query=MATCH ()-[p:route]->() RETURN p LIMIT 10" -k https://localhost:8182/openCypher -d "explain=details"                                                                                              ~
Query:
MATCH ()-[p:route]->() RETURN p LIMIT 10

╔════╤════════╤════════╤═══════════════════╤════════════════════╤═════════════════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments          │ Mode                │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪════════════════════╪═════════════════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]     │ -                   │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFESubquery       │ subQuery=subQuery1 │ -                   │ 0        │ 10        │ 0.00  │ 5.00      ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ -      │ -      │ TermResolution    │ vars=[?p]          │ id2value_opencypher │ 10       │ 10        │ 1.00  │ 1.00      ║
╚════╧════════╧════════╧═══════════════════╧════════════════════╧═════════════════════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery1
╔════╤════════╤════════╤═════════════════╤═══════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name            │ Arguments                                                 │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═════════════════╪═══════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFEPipelineScan │ pattern=Edge((?anon_node7)-[?p:?p_type1]->(?anon_node21)) │ -    │ 0        │ 1000      │ 0.00  │ 0.66      ║
║    │        │        │                 │ inlineFilters=[(?p_type1 IN [<el://route>])]              │      │          │           │       │           ║
║    │        │        │                 │ patternEstimate=26219                                     │      │          │           │       │           ║
╟────┼────────┼────────┼─────────────────┼───────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFEProject      │ columns=[?p]                                              │ -    │ 1000     │ 1000      │ 1.00  │ 0.14      ║
╟────┼────────┼────────┼─────────────────┼───────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ -      │ -      │ DFEDrain        │ limit=10                                                  │ -    │ 1000     │ 0         │ 0.00  │ 0.11      ║
╚════╧════════╧════════╧═════════════════╧═══════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝
```

# Contoh `explain` output untuk fungsi ekspresi nilai
<a name="access-graph-opencypher-explain-example-3"></a>

Fungsinya adalah:

```
MATCH (a) RETURN DISTINCT labels(a)
```

Pada `explain` output di bawah ini, `DFEPipelineScan` (ID 0) memindai semua label node. Ini sesuai dengan`MATCH (a`).

`DFEChunkLocalSubquery`(ID 1) mengumpulkan label `?a` untuk masing-masing`?a`. Ini sesuai dengan`labels(a)`. Anda dapat melihatnya melalui `DFEApply` dan`DFEReduce`.

`BindRelation`(ID 2) digunakan untuk mengganti nama kolom generik `?__gen_labelsOfa2` menjadi. `?labels(a)`

`DFEDistinctRelation`(ID 4) hanya mengambil label yang berbeda (multiple:airport node akan memberikan label duplikat (a): ["airport"]). Ini sesuai dengan`DISTINCT labels(a)`.

```
curl -d "query=MATCH (a) RETURN DISTINCT labels(a)" -k https://localhost:8182/openCypher -d "explain=details"                                                                                                    ~
Query:
MATCH (a) RETURN DISTINCT labels(a)

╔════╤════════╤════════╤═══════════════════╤════════════════════╤═════════════════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments          │ Mode                │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪════════════════════╪═════════════════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]     │ -                   │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFESubquery       │ subQuery=subQuery1 │ -                   │ 0        │ 5         │ 0.00  │ 81.00     ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ -      │ -      │ TermResolution    │ vars=[?labels(a)]  │ id2value_opencypher │ 5        │ 5         │ 1.00  │ 1.00      ║
╚════╧════════╧════════╧═══════════════════╧════════════════════╧═════════════════════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery1
╔════╤════════╤════════╤═══════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                  │ Arguments                                                                                                    │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFEPipelineScan       │ pattern=Node(?a) with property 'ALL' and label '?a_label1'                                                   │ -    │ 0        │ 3750      │ 0.00  │ 26.77     ║
║    │        │        │                       │ patternEstimate=3506                                                                                         │      │          │           │       │           ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#8b314f55-2cc7-456a-a48a-c76a0465cfab/graph_1 │ -    │ 3750     │ 3750      │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ DFEBindRelation       │ inputVars=[?a, ?__gen_labelsOfa2, ?__gen_labelsOfa2]                                                         │ -    │ 3750     │ 3750      │ 1.00  │ 0.08      ║
║    │        │        │                       │ outputVars=[?a, ?__gen_labelsOfa2, ?labels(a)]                                                               │      │          │           │       │           ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ DFEProject            │ columns=[?labels(a)]                                                                                         │ -    │ 3750     │ 3750      │ 1.00  │ 0.05      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ DFEDistinctRelation   │ -                                                                                                            │ -    │ 3750     │ 5         │ 0.00  │ 2.78      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ -      │ -      │ DFEDrain              │ -                                                                                                            │ -    │ 5        │ 0         │ 0.00  │ 0.03      ║
╚════╧════════╧════════╧═══════════════════════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#8b314f55-2cc7-456a-a48a-c76a0465cfab/graph_1
╔════╤════════╤════════╤══════════════════════╤════════════════════════════════════════════════════════════╤══════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                 │ Arguments                                                  │ Mode     │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪══════════════════════╪════════════════════════════════════════════════════════════╪══════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFESolutionInjection │ outSchema=[?a]                                             │ -        │ 0        │ 3750      │ 0.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ 3      │ DFETee               │ -                                                          │ -        │ 3750     │ 7500      │ 2.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 4      │ -      │ DFEProject           │ columns=[?a]                                               │ -        │ 3750     │ 3750      │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 17     │ -      │ DFEOptionalJoin      │ -                                                          │ -        │ 7500     │ 3750      │ 0.50  │ 0.44      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ DFEDistinctRelation  │ -                                                          │ -        │ 3750     │ 3750      │ 1.00  │ 2.23      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ 6      │ -      │ DFEDistinctColumn    │ column=?a                                                  │ -        │ 3750     │ 3750      │ 1.00  │ 1.50      ║
║    │        │        │                      │ ordered=false                                              │          │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 6  │ 7      │ -      │ DFEPipelineJoin      │ pattern=Node(?a) with property 'ALL' and label '?a_label3' │ -        │ 3750     │ 3750      │ 1.00  │ 10.58     ║
║    │        │        │                      │ patternEstimate=3506                                       │          │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 7  │ 8      │ 9      │ DFETee               │ -                                                          │ -        │ 3750     │ 7500      │ 2.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 8  │ 10     │ -      │ DFEBindRelation      │ inputVars=[?a_label3]                                      │ -        │ 3750     │ 3750      │ 1.00  │ 0.04      ║
║    │        │        │                      │ outputVars=[?100]                                          │          │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 9  │ 11     │ -      │ DFEBindRelation      │ inputVars=[?a, ?a_label3, ?100]                            │ -        │ 7500     │ 3750      │ 0.50  │ 0.07      ║
║    │        │        │                      │ outputVars=[?a, ?a_label3, ?100]                           │          │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 10 │ 9      │ -      │ DFETermResolution    │ column=?100                                                │ id2value │ 3750     │ 3750      │ 1.00  │ 7.60      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 11 │ 12     │ -      │ DFEBindRelation      │ inputVars=[?a, ?a_label3, ?100]                            │ -        │ 3750     │ 3750      │ 1.00  │ 0.06      ║
║    │        │        │                      │ outputVars=[?a, ?100, ?a_label3]                           │          │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 12 │ 13     │ -      │ DFEApply             │ functor=nodeLabel(?a_label3)                               │ -        │ 3750     │ 3750      │ 1.00  │ 0.55      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 13 │ 14     │ -      │ DFEProject           │ columns=[?a, ?a_label3_alias4]                             │ -        │ 3750     │ 3750      │ 1.00  │ 0.05      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 14 │ 15     │ -      │ DFEMergeChunks       │ -                                                          │ -        │ 3750     │ 3750      │ 1.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 15 │ 16     │ -      │ DFEReduce            │ functor=collect(?a_label3_alias4)                          │ -        │ 3750     │ 3750      │ 1.00  │ 6.37      ║
║    │        │        │                      │ segmentationKey=[?a]                                       │          │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 16 │ 3      │ -      │ DFEMergeChunks       │ -                                                          │ -        │ 3750     │ 3750      │ 1.00  │ 0.03      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 17 │ -      │ -      │ DFEDrain             │ -                                                          │ -        │ 3750     │ 0         │ 0.00  │ 0.02      ║
╚════╧════════╧════════╧══════════════════════╧════════════════════════════════════════════════════════════╧══════════╧══════════╧═══════════╧═══════╧═══════════╝
```

# Contoh `explain` output untuk fungsi ekspresi nilai matematika
<a name="access-graph-opencypher-explain-example-4"></a>

Dalam contoh ini, `RETURN abs(-10)` melakukan evaluasi sederhana, mengambil nilai absolut dari konstanta,`-10`.

`DFEChunkLocalSubQuery`(ID 1) melakukan injeksi solusi untuk nilai statis`-10`, yang disimpan dalam variabel,`?100`.

`DFEApply`(ID 2) adalah operator yang menjalankan fungsi nilai absolut `abs()` pada nilai statis yang disimpan dalam `?100` variabel.

Berikut adalah query dan `explain` output yang dihasilkan:

```
curl -d "query=RETURN abs(-10)" -k https://localhost:8182/openCypher  -d "explain=details"                                                                                                                       ~
Query:
RETURN abs(-10)

╔════╤════════╤════════╤═══════════════════╤═══════════════════════╤═════════════════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments             │ Mode                │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪═══════════════════════╪═════════════════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]        │ -                   │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFESubquery       │ subQuery=subQuery1    │ -                   │ 0        │ 1         │ 0.00  │ 4.00      ║
╟────┼────────┼────────┼───────────────────┼───────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ -      │ -      │ TermResolution    │ vars=[?_internalVar1] │ id2value_opencypher │ 1        │ 1         │ 1.00  │ 1.00      ║
╚════╧════════╧════════╧═══════════════════╧═══════════════════════╧═════════════════════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery1
╔════╤════════╤════════╤═══════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                  │ Arguments                                                                                                    │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFESolutionInjection  │ outSchema=[]                                                                                                 │ -    │ 0        │ 1         │ 0.00  │ 0.01      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#c4cc6148-cce3-4561-93c0-deb91f257356/graph_1 │ -    │ 1        │ 1         │ 1.00  │ 0.03      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ DFEApply              │ functor=abs(?100)                                                                                            │ -    │ 1        │ 1         │ 1.00  │ 0.26      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ DFEBindRelation       │ inputVars=[?_internalVar2, ?_internalVar2]                                                                   │ -    │ 1        │ 1         │ 1.00  │ 0.04      ║
║    │        │        │                       │ outputVars=[?_internalVar2, ?_internalVar1]                                                                  │      │          │           │       │           ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ DFEProject            │ columns=[?_internalVar1]                                                                                     │ -    │ 1        │ 1         │ 1.00  │ 0.06      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ -      │ -      │ DFEDrain              │ -                                                                                                            │ -    │ 1        │ 0         │ 0.00  │ 0.05      ║
╚════╧════════╧════════╧═══════════════════════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝

subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#c4cc6148-cce3-4561-93c0-deb91f257356/graph_1
╔════╤════════╤════════╤══════════════════════╤═════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                 │ Arguments                           │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪══════════════════════╪═════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFESolutionInjection │ solutions=[?100 -> [-10^^<LONG>]]   │ -    │ 0        │ 1         │ 0.00  │ 0.01      ║
║    │        │        │                      │ outSchema=[?100]                    │      │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 3      │ -      │ DFERelationalJoin    │ joinVars=[]                         │ -    │ 2        │ 1         │ 0.50  │ 0.18      ║
╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 1      │ -      │ DFESolutionInjection │ outSchema=[]                        │ -    │ 0        │ 1         │ 0.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼─────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ -      │ -      │ DFEDrain             │ -                                   │ -    │ 1        │ 0         │ 0.00  │ 0.02      ║
╚════╧════════╧════════╧══════════════════════╧═════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝
```

# Contoh `explain` output untuk kueri jalur panjang variabel (VLP)
<a name="access-graph-opencypher-explain-example-5"></a>

Ini adalah contoh rencana kueri yang lebih kompleks untuk menangani kueri jalur panjang variabel. Contoh ini hanya menunjukkan bagian dari `explain` output, untuk kejelasan.

Dalam`subQuery1`, `DFEPipelineScan` (ID 0) dan `DFEChunkLocalSubQuery` (ID 1), yang menyuntikkan `...graph_1` subquery, bertanggung jawab untuk memindai node dengan kode. `YPO`

Dalam`subQuery1`, `DFEChunkLocalSubQuery` (ID 2), yang menyuntikkan `...graph_2` subquery, bertanggung jawab untuk memindai node dengan kode. `LAX`

Dalam`subQuery1`, `DFEChunkLocalSubQuery` (ID 3) menyuntikkan `...graph3` subquery, yang berisi `DFELoopSubQuery` (ID 17), yang pada gilirannya menyuntikkan subquery. `...graph5` Operasi ini bertanggung jawab untuk menyelesaikan pola `-[*2]->` panjang variabel dalam string kueri antara dua node.

```
curl -d "query=MATCH p=(a {code: 'YPO'})-[*2]->(b{code: 'LAX'}) return p" -k https://localhost:8182/openCypher -d "explain=details"                                                                                                                                                                                ~
Query:
MATCH p=(a {code: 'YPO'})-[*2]->(b{code: 'LAX'}) return p

╔════╤════════╤════════╤═══════════════════╤════════════════════╤═════════════════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments          │ Mode                │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪════════════════════╪═════════════════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]     │ -                   │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFESubquery       │ subQuery=subQuery1 │ -                   │ 0        │ 0         │ 0.00  │ 84.00     ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ -      │ -      │ TermResolution    │ vars=[?p]          │ id2value_opencypher │ 0        │ 0         │ 0.00  │ 0         ║
╚════╧════════╧════════╧═══════════════════╧════════════════════╧═════════════════════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery1
╔════╤════════╤════════╤═══════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                  │ Arguments                                                                                                    │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFEPipelineScan       │ pattern=Node(?a) with property 'code' as ?a_code7 and label 'ALL'                                            │ -    │ 0        │ 1         │ 0.00  │ 0.68      ║
║    │        │        │                       │ inlineFilters=[(?a_code7 IN ["YPO"^^xsd:string])]                                                            │      │          │           │       │           ║
║    │        │        │                       │ patternEstimate=1                                                                                            │      │          │           │       │           ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#cc05129f-d07e-4622-bbe3-9e99558eca46/graph_1 │ -    │ 1        │ 1         │ 1.00  │ 0.03      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#cc05129f-d07e-4622-bbe3-9e99558eca46/graph_2 │ -    │ 1        │ 1         │ 1.00  │ 0.02      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#cc05129f-d07e-4622-bbe3-9e99558eca46/graph_3 │ -    │ 1        │ 0         │ 0.00  │ 0.04      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ DFEBindRelation       │ inputVars=[?__gen_path6, ?anon_rel26, ?b_code8, ?b, ?a_code7, ?a, ?__gen_path6]                              │ -    │ 0        │ 0         │ 0.00  │ 0.10      ║
║    │        │        │                       │ outputVars=[?__gen_path6, ?anon_rel26, ?b_code8, ?b, ?a_code7, ?a, ?p]                                       │      │          │           │       │           ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ 6      │ -      │ DFEProject            │ columns=[?p]                                                                                                 │ -    │ 0        │ 0         │ 0.00  │ 0.05      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 6  │ -      │ -      │ DFEDrain              │ -                                                                                                            │ -    │ 0        │ 0         │ 0.00  │ 0.02      ║
╚════╧════════╧════════╧═══════════════════════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#cc05129f-d07e-4622-bbe3-9e99558eca46/graph_1
╔════╤════════╤════════╤══════════════════════╤════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                 │ Arguments                                                  │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪══════════════════════╪════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFESolutionInjection │ outSchema=[?a, ?a_code7]                                   │ -    │ 0        │ 1         │ 0.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ 3      │ DFETee               │ -                                                          │ -    │ 1        │ 2         │ 2.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 4      │ -      │ DFEDistinctColumn    │ column=?a                                                  │ -    │ 1        │ 1         │ 1.00  │ 0.25      ║
║    │        │        │                      │ ordered=false                                              │      │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 5      │ -      │ DFEHashIndexBuild    │ vars=[?a]                                                  │ -    │ 1        │ 1         │ 1.00  │ 0.05      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ DFEPipelineJoin      │ pattern=Node(?a) with property 'ALL' and label '?a_label1' │ -    │ 1        │ 1         │ 1.00  │ 0.47      ║
║    │        │        │                      │ patternEstimate=3506                                       │      │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ 6      │ 7      │ DFESync              │ -                                                          │ -    │ 2        │ 2         │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 6  │ 8      │ -      │ DFEForwardValue      │ -                                                          │ -    │ 1        │ 1         │ 1.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 7  │ 8      │ -      │ DFEForwardValue      │ -                                                          │ -    │ 1        │ 1         │ 1.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 8  │ 9      │ -      │ DFEHashIndexJoin     │ -                                                          │ -    │ 2        │ 1         │ 0.50  │ 0.26      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 9  │ -      │ -      │ DFEDrain             │ -                                                          │ -    │ 1        │ 0         │ 0.00  │ 0.02      ║
╚════╧════════╧════════╧══════════════════════╧════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#cc05129f-d07e-4622-bbe3-9e99558eca46/graph_2
╔════╤════════╤════════╤══════════════════════╤═══════════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                 │ Arguments                                                         │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪══════════════════════╪═══════════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFEPipelineScan      │ pattern=Node(?b) with property 'code' as ?b_code8 and label 'ALL' │ -    │ 0        │ 1         │ 0.00  │ 0.38      ║
║    │        │        │                      │ inlineFilters=[(?b_code8 IN ["LAX"^^xsd:string])]                 │      │          │           │       │           ║
║    │        │        │                      │ patternEstimate=1                                                 │      │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼───────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFEMergeChunks       │ -                                                                 │ -    │ 1        │ 1         │ 1.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼───────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 4      │ -      │ DFERelationalJoin    │ joinVars=[]                                                       │ -    │ 2        │ 1         │ 0.50  │ 0.19      ║
╟────┼────────┼────────┼──────────────────────┼───────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 2      │ -      │ DFESolutionInjection │ outSchema=[?a, ?a_code7]                                          │ -    │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼──────────────────────┼───────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ -      │ -      │ DFEDrain             │ -                                                                 │ -    │ 1        │ 0         │ 0.00  │ 0.01      ║
╚════╧════════╧════════╧══════════════════════╧═══════════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#cc05129f-d07e-4622-bbe3-9e99558eca46/graph_3
╔════╤════════╤════════╤═══════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                  │ Arguments                                                                                                    │ Mode     │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════════╪══════════╪═══════════╪═══════╪═══════════╣
...
║ 17 │ 18     │ -      │ DFELoopSubQuery       │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#cc05129f-d07e-4622-bbe3-9e99558eca46/graph_5 │ -        │ 1        │ 2         │ 2.00  │ 0.31      ║
...
```

# Transaksi di Neptunus OpenCypher
<a name="access-graph-opencypher-transactions"></a>

Implementasi OpenCypher di Amazon Neptunus menggunakan [semantik transaksi yang ditentukan oleh Neptunus Namun, tingkat isolasi yang disediakan oleh driver Bolt memiliki beberapa implikasi](transactions-neptune.md) spesifik untuk semantik transaksi Bolt, seperti yang dijelaskan pada bagian di bawah ini.

## Kueri transaksi Bolt hanya-baca
<a name="access-graph-opencypher-transactions-ro"></a>

Ada berbagai cara agar kueri hanya-baca dapat diproses, dengan model transaksi dan tingkat isolasi yang berbeda, sebagai berikut:

### Kueri transaksi hanya-baca implisit
<a name="access-graph-opencypher-transactions-ro-implicit"></a>

Berikut adalah contoh transaksi implisit read-only:

```
public void executeReadImplicitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // read query
  final String READ_QUERY = "MATCH (n) RETURN n limit 10";

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
          Config.builder().withEncryption()
                          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
                          .build());

  // create the session config
  SessionConfig sessionConfig = SessionConfig.builder()
                                             .withFetchSize(1000)
                                             .withDefaultAccessMode(AccessMode.READ)
                                             .build();

  // run the query as access mode read
  driver.session(sessionConfig).readTransaction(new TransactionWork<String>()
    {
      final StringBuilder resultCollector = new StringBuilder();

      @Override
      public String execute(final Transaction tx)
      {
        // execute the query
        Result queryResult = tx.run(READ_QUERY);

        // Read the result
        for (Record record : queryResult.list())
        {
          for (String key : record.keys())
          {
            resultCollector.append(key)
                           .append(":")
                           .append(record.get(key).asNode().toString());
          }
        }
        return resultCollector.toString();
      }

    }
  );

  // close the driver.
  driver.close();
}
```

Karena replika baca hanya menerima kueri hanya-baca, semua kueri terhadap replika baca dijalankan sebagai transaksi baca-implisit terlepas dari mode akses yang ditetapkan dalam konfigurasi sesi. [Neptunus mengevaluasi transaksi baca-implisit sebagai kueri hanya-baca di bawah semantik isolasi.](transactions-neptune.md#transactions-neptune-read-only) `SNAPSHOT`

Jika terjadi kegagalan, transaksi baca-implisit dicoba ulang secara default.

### Kueri transaksi hanya-baca otomatis
<a name="access-graph-opencypher-transactions-ro-autocommit"></a>

Berikut adalah contoh transaksi autocommit read-only:

```
public void executeAutoCommitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // read query
  final String READ_QUERY = "MATCH (n) RETURN n limit 10";

  // Create the session config.
  final SessionConfig sessionConfig = SessionConfig
    .builder()
    .withFetchSize(1000)
    .withDefaultAccessMode(AccessMode.READ)
    .build();

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
    Config.builder()
          .withEncryption()
          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
          .build());

  // result collector
  final StringBuilder resultCollector = new StringBuilder();

  // create a session
  final Session session = driver.session(sessionConfig);

  // run the query
  final Result queryResult = session.run(READ_QUERY);
  for (final Record record : queryResult.list())
  {
    for (String key : record.keys())
    {
      resultCollector.append(key)
                     .append(":")
                     .append(record.get(key).asNode().toString());
    }
  }

  // close the session
  session.close();

  // close the driver
  driver.close();
}
```

[Jika mode akses diatur ke `READ` dalam konfigurasi sesi, Neptunus mengevaluasi kueri transaksi autocommit sebagai kueri hanya-baca di bawah semantik isolasi.](transactions-neptune.md#transactions-neptune-read-only) `SNAPSHOT` Perhatikan bahwa replika baca hanya menerima kueri hanya-baca.

Jika Anda tidak meneruskan konfigurasi sesi, kueri komit otomatis diproses secara default dengan isolasi kueri mutasi, jadi penting untuk meneruskan konfigurasi sesi yang secara eksplisit menyetel mode akses ke. `READ`

Jika terjadi kegagalan, kueri komit otomatis hanya-baca tidak dicoba ulang.

### Kueri transaksi hanya-baca eksplisit
<a name="access-graph-opencypher-transactions-ro-explicit"></a>

Berikut adalah contoh transaksi hanya-baca eksplisit:

```
public void executeReadExplicitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // read query
  final String READ_QUERY = "MATCH (n) RETURN n limit 10";

  // Create the session config.
  final SessionConfig sessionConfig = SessionConfig
    .builder()
    .withFetchSize(1000)
    .withDefaultAccessMode(AccessMode.READ)
    .build();

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
    Config.builder()
          .withEncryption()
          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
          .build());

  // result collector
  final StringBuilder resultCollector = new StringBuilder();

  // create a session
  final Session session = driver.session(sessionConfig);

  // begin transaction
  final Transaction tx = session.beginTransaction();

  // run the query on transaction
  final List<Record> list = tx.run(READ_QUERY).list();

  // read the result
  for (final Record record : list)
  {
    for (String key : record.keys())
    {
      resultCollector
        .append(key)
        .append(":")
        .append(record.get(key).asNode().toString());
    }
  }

  // commit the transaction and for rollback we can use beginTransaction.rollback();
  tx.commit();

  // close the driver
  driver.close();
}
```

[Jika mode akses diatur ke `READ` dalam konfigurasi sesi, Neptunus mengevaluasi transaksi hanya-baca eksplisit sebagai kueri hanya-baca di bawah semantik isolasi.](transactions-neptune.md#transactions-neptune-read-only) `SNAPSHOT` Perhatikan bahwa replika baca hanya menerima kueri hanya-baca.

Jika Anda tidak meneruskan konfigurasi sesi, transaksi hanya-baca eksplisit diproses secara default dengan isolasi kueri mutasi, jadi penting untuk meneruskan konfigurasi sesi yang secara eksplisit menyetel mode akses ke. `READ`

Jika terjadi kegagalan, kueri eksplisit hanya-baca akan dicoba ulang secara default.

## Kueri transaksi Mutasi Bolt
<a name="access-graph-opencypher-transactions-wr"></a>

Seperti halnya kueri hanya-baca, ada berbagai cara agar kueri mutasi dapat diproses, dengan model transaksi dan tingkat isolasi yang berbeda, sebagai berikut:

### Kueri transaksi mutasi implisit
<a name="access-graph-opencypher-transactions-wr-implicit"></a>

Berikut adalah contoh transaksi mutasi implisit:

```
public void executeWriteImplicitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // create node with label as label and properties.
  final String WRITE_QUERY = "CREATE (n:label {name : 'foo'})";

  // Read the vertex created with label as label.
  final String READ_QUERY = "MATCH (n:label) RETURN n";

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
    Config.builder()
          .withEncryption()
          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
          .build());

  // create the session config
  SessionConfig sessionConfig = SessionConfig
    .builder()
    .withFetchSize(1000)
    .withDefaultAccessMode(AccessMode.WRITE)
    .build();

  final StringBuilder resultCollector = new StringBuilder();

  // run the query as access mode write
  driver.session(sessionConfig).writeTransaction(new TransactionWork<String>()
  {
    @Override
    public String execute(final Transaction tx)
    {
      // execute the write query and consume the result.
      tx.run(WRITE_QUERY).consume();

      // read the vertex written in the same transaction
      final List<Record> list = tx.run(READ_QUERY).list();

      // read the result
      for (final Record record : list)
      {
        for (String key : record.keys())
        {
          resultCollector
            .append(key)
            .append(":")
            .append(record.get(key).asNode().toString());
        }
      }
      return resultCollector.toString();
    }
  }); // at the end, the transaction is automatically committed.

  // close the driver.
  driver.close();
}
```

[Pembacaan yang dibuat sebagai bagian dari kueri mutasi dijalankan secara `READ COMMITTED` terpisah dengan jaminan biasa untuk transaksi mutasi Neptunus.](transactions-neptune.md#transactions-neptune-mutation)

Apakah Anda secara khusus lulus dalam konfigurasi sesi, transaksi selalu diperlakukan sebagai transaksi tulis.

Untuk konflik, lihat[Resolusi Konflik Menggunakan Lock-Wait Timeout](transactions-neptune.md#transactions-neptune-conflicts).

### Kueri transaksi mutasi komit otomatis
<a name="access-graph-opencypher-transactions-wr-autocommit"></a>

Kueri autocommit mutasi mewarisi perilaku yang sama dengan transaksi implisit mutasi.

Jika Anda tidak lulus dalam konfigurasi sesi, transaksi diperlakukan sebagai transaksi tulis secara default.

Jika terjadi kegagalan, kueri komit otomatis mutasi tidak dicoba ulang secara otomatis.

### Kueri transaksi mutasi eksplisit
<a name="access-graph-opencypher-transactions-wr-explicit"></a>

Berikut adalah contoh transaksi mutasi eksplisit:

```
public void executeWriteExplicitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // create node with label as label and properties.
  final String WRITE_QUERY = "CREATE (n:label {name : 'foo'})";

  // Read the vertex created with label as label.
  final String READ_QUERY = "MATCH (n:label) RETURN n";

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
    Config.builder()
          .withEncryption()
          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
          .build());

  // create the session config
  SessionConfig sessionConfig = SessionConfig
    .builder()
    .withFetchSize(1000)
    .withDefaultAccessMode(AccessMode.WRITE)
    .build();

  final StringBuilder resultCollector = new StringBuilder();

  final Session session = driver.session(sessionConfig);

  // run the query as access mode write
  final Transaction tx = driver.session(sessionConfig).beginTransaction();

  // execute the write query and consume the result.
  tx.run(WRITE_QUERY).consume();

  // read the result from the previous write query in a same transaction.
  final List<Record> list = tx.run(READ_QUERY).list();

  // read the result
  for (final Record record : list)
  {
    for (String key : record.keys())
    {
      resultCollector
        .append(key)
        .append(":")
        .append(record.get(key).asNode().toString());
    }
  }

  // commit the transaction and for rollback we can use tx.rollback();
  tx.commit();

  // close the session
  session.close();

  // close the driver.
  driver.close();
}
```

Kueri mutasi eksplisit mewarisi perilaku yang sama dengan transaksi mutasi implisit.

Jika Anda tidak lulus dalam konfigurasi sesi, transaksi diperlakukan sebagai transaksi tulis secara default.

Untuk konflik, lihat[Resolusi Konflik Menggunakan Lock-Wait Timeout](transactions-neptune.md#transactions-neptune-conflicts).

# Petunjuk kueri OpenCypher
<a name="opencypher-query-hints"></a>

**penting**  
 [Petunjuk kueri OpenCypher hanya tersedia dari rilis mesin 1.3.2.0 dan yang lebih baru.](https://docs.aws.amazon.com//neptune/latest/userguide/engine-releases-1.3.2.0.html) 

 Di Amazon Neptunus, Anda dapat menggunakan `USING` klausa untuk menentukan petunjuk kueri untuk kueri OpenCypher. Petunjuk ini memungkinkan Anda untuk mengontrol strategi pengoptimalan dan evaluasi. 

 Sintaks untuk petunjuk kueri adalah: 

```
USING {scope}:{hint} {value}
```

1.  `{scope}`mendefinisikan ruang lingkup di mana petunjuk berlaku untuk: `Query` atau. `Clause` 

    Nilai lingkup `Query` berarti bahwa petunjuk kueri berlaku untuk seluruh kueri (tingkat kueri). 

    Nilai cakupan `Clause` berarti bahwa petunjuk kueri berlaku untuk klausa yang didahului petunjuk (tingkat klausa). 

1.  `{hint}`adalah nama petunjuk kueri yang diterapkan. 

1.  `{value}`adalah argumen untuk`{hint}`. 

 Nilainya bisa tidak peka huruf besar/kecil. 

 Misalnya, untuk mengaktifkan cache rencana kueri untuk kueri: 

```
Using QUERY:PLANCACHE "enabled" 
MATCH (a:Person {firstName: "Erin", lastName: $lastName})
 RETURN a
```

**catatan**  
 **Saat ini, petunjuk **kueri** lingkup Kueri **PLANCACHE**, **TIMEOUTMILLISECONDS**, dan Jenis didukung. assumeConsistentData** Petunjuk kueri yang didukung tercantum di bawah ini. 

**Topics**
+ [Petunjuk cache rencana kueri OpenCypher](opencypher-query-hints-qpc-hint.md)
+ [AssumeConsistentDataTypes petunjuk](opencypher-query-hints-AssumeConsistentDataTypes.md)
+ [Petunjuk batas waktu kueri OpenCypher](opencypher-query-hints-timeout-hint.md)

# Petunjuk cache rencana kueri OpenCypher
<a name="opencypher-query-hints-qpc-hint"></a>

 Perilaku cache rencana kueri dapat diganti berdasarkan per-kueri (diparameterisasi atau tidak) dengan petunjuk kueri tingkat kueri. `QUERY:PLANCACHE` Itu perlu digunakan dengan `USING` klausa. Petunjuk kueri menerima `enabled` atau `disabled` sebagai nilai. Untuk informasi selengkapnya tentang cache paket kueri, lihat[Cache paket kueri di Amazon Neptunus](access-graph-qpc.md). 

```
# Forcing plan to be cached or reused
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"enabled\" MATCH(n) RETURN n LIMIT 1"
  
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"enabled\" RETURN \$arg" \
  -d "parameters={\"arg\": 123}"
  
# Forcing plan to be neither cached nor reused
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"disabled\" MATCH(n) RETURN n LIMIT 1"
```

# AssumeConsistentDataTypes petunjuk
<a name="opencypher-query-hints-AssumeConsistentDataTypes"></a>

 OpenCypher mengikuti paradigma di mana kecocokan tipe data numerik (misalnya, int, byte, pendek, panjang, dll.) dilakukan di bawah semantik promosi tipe. Misalnya, ketika mencari semua properti dengan nilai input 10 dengan tipe pendek, di bawah semantik promosi tipe, itu juga akan cocok dengan properti yang memiliki 10 sebagai nilai panjang. Dalam beberapa kasus, pengecoran tipe dapat menyebabkan overhead dan menghasilkan rencana kueri yang kurang efisien daripada jika tidak ada pengecoran tipe yang dilakukan. Khususnya dalam kasus di mana tipe data digunakan secara konsisten dalam data (misalnya, jika semua usia orang disimpan sebagai nilai panjang) melakukan promosi tipe menyebabkan overhead tanpa memengaruhi hasil kueri. 

 Untuk memungkinkan pengoptimalan kasus ketika diketahui bahwa nilai data properti numerik yang disimpan dalam database adalah tipe yang konsisten, petunjuk kueri yang disebut `assumeConsistentDataTypes` (dengan nilai`true/false`, dengan default`false`) dapat digunakan. Ketika petunjuk kueri ini diberikan dengan nilai`true`, mesin mengasumsikan satu-satunya nilai properti selalu panjang atau ganda dan akan melewati semantik promosi jenis. Nilai numerik yang ditentukan dalam kueri dianggap sebagai nilai panjang (untuk nilai non-floating point) dan ganda (untuk nilai floating point). 

 Jika data secara konsisten menggunakan tipe data tunggal (misalnya semua usia disimpan sebagai`long`), maka menggunakan `assumeConsistentDataTypes` petunjuk dapat mengoptimalkan kueri dengan melewatkan pemeriksaan kesetaraan yang tidak perlu untuk jenis numerik yang berbeda. Namun, jika data memiliki tipe data yang tidak konsisten untuk properti yang sama, maka menggunakan petunjuk dapat menyebabkan beberapa hasil terlewatkan, karena kueri hanya akan cocok dengan tipe data tunggal yang diasumsikan oleh petunjuk. 

```
# Database loaded with following openCypher CSV's

# File 1
:ID,age:Int
n1,20
n2,25

# File 2
:ID,age:Long
n3,25


# Example (no hint)
MATCH (n:Person) 
WHERE n.age >= 25
RETURN n

# Result
n2
n3

Returns all person whose age is >= 25 and the values >= 25 can be with any of these datatypes
i.e. byte, short, int, long, double or float

-----------------------------------------------------------------------------------

# Example (with hint present)
USING QUERY:assumeConsistentDataTypes "true"
MATCH (n:Person)
WHERE n.age >= 25
RETURN n

# Result
n3

Returns only "n3" and not "n2". The reason is that even though the numerical value
matches (25), the datatype is "int" and is considered a non-match.
```

 Perbedaannya juga dapat divalidasi melalui penjelasan. 

 Tanpa penjelasan: 

```
# Query
MATCH (n)
WHERE n.age = 20
RETURN n

# Explain Snippet
╔═════╤══════════╤══════════╤══════════════════════════════╤═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╤════════╤════════════╤══════════════╤═════════╤══════════════╗
║ ID │ Out #1 │ Out #2 │ Name                   │ Arguments                                                                                                                            │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠═════╪══════════╪══════════╪══════════════════════════════╪═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╪════════╪════════════╪══════════════╪═════════╪══════════════╣
║ 0  │ 1      │ -      │ DFEPipelineScan (DFX)  │ pattern=Node(?n) with property 'age' as ?n_age2 and label 'ALL'                                                                      │ -    │ 0        │ 1         │ 0.00  │ 0.10      ║
║    │        │        │                        │ inlineFilters=[(?n_age2 IN ["20"^^xsd:byte, "20"^^xsd:int, "20"^^xsd:long, "20"^^xsd:short, "20.0"^^xsd:double, "20.0"^^xsd:float])] │      │          │           │       │           ║
║    │        │        │                        │ patternEstimate=1                                                                                                                    │      │          │           │       │           ║
╟─────┼──────────┼──────────┼──────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼────────────┼──────────────┼─────────┼──────────────╢

# The inFilters field contains all numeric types
```

 Dengan petunjuk: 

```
# Query
MATCH (n)
WHERE n.age = 20
RETURN n

# Explain Snippet
╔═════╤══════════╤══════════╤══════════════════════════════╤═════════════════════════════════════════════════════════════════════════════════╤════════╤════════════╤══════════════╤═════════╤══════════════╗
║ ID │ Out #1 │ Out #2 │ Name                   │ Arguments                                                       │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠═════╪══════════╪══════════╪══════════════════════════════╪═════════════════════════════════════════════════════════════════════════════════╪════════╪════════════╪══════════════╪═════════╪══════════════╣
║ 0  │ 1      │ -      │ DFEPipelineScan (DFX)  │ pattern=Node(?n) with property 'age' as ?n_age2 and label 'ALL' │ -    │ 0        │ 1         │ 0.00  │ 0.07      ║
║    │        │        │                        │ inlineFilters=[(?n_age2 IN ["20"^^xsd:long])]                   │      │          │           │       │           ║
║    │        │        │                        │ patternEstimate=1                                               │      │          │           │       │           ║
╟─────┼──────────┼──────────┼──────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┼────────┼────────────┼──────────────┼─────────┼──────────────╢

# The inFilters field only contains long datatype
```

# Petunjuk batas waktu kueri OpenCypher
<a name="opencypher-query-hints-timeout-hint"></a>

 Perilaku batas waktu kueri dapat dikonfigurasi berdasarkan per-kueri dengan petunjuk kueri tingkat kueri. `QUERY:TIMEOUTMILLISECONDS` Itu harus digunakan dengan `USING` klausa. Petunjuk kueri menerima panjang non-negatif sebagai nilai. 

```
# Using query-level timeout hint 

% curl https://<endpoint>:<port>/opencypher \
  -d "query=USING QUERY:TIMEOUTMILLISECONDS 100 MATCH(n) RETURN n LIMIT 1"
```

 Perilaku batas waktu kueri akan mempertimbangkan batas waktu minimum tingkat cluster dan batas waktu tingkat kueri. Silakan lihat contoh di bawah ini untuk memahami perilaku batas waktu kueri. [Untuk informasi selengkapnya tentang batas waktu kueri tingkat cluster, lihat neptune\$1query\$1timeout.](https://docs.aws.amazon.com/neptune/latest/userguide/parameters.html#parameters-db-cluster-parameters-neptune_query_timeout) 

```
# Suppose `neptune_query_timeout` is 10000 ms and query-level timeout is set to 100 ms
# It will consider 100 ms as the final timeout 

% curl https://<endpoint>:<port>/opencypher \
  -d "query=USING QUERY:TIMEOUTMILLISECONDS 100 MATCH(n) RETURN n LIMIT 1"

# Suppose `neptune_query_timeout` is 100 ms and query-level timeout is set to 10000 ms
# It will still consider 100 ms as the final timeout 

% curl https://<endpoint>:<port>/opencypher \
  -d "query=USING QUERY:TIMEOUTMILLISECONDS 10000 MATCH(n) RETURN n LIMIT 1"
```

# Pembatasan Neptunus OpenCypher
<a name="access-graph-opencypher-limitations"></a>

Rilis Amazon Neptunus dari OpenCypher masih tidak mendukung semua yang ditentukan dalam [Referensi Bahasa Kueri Cypher, Versi](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf) 9, seperti yang dirinci dalam. [Kepatuhan spesifikasi OpenCypher](feature-opencypher-compliance.md) Rilis masa depan diharapkan dapat mengatasi banyak keterbatasan tersebut.

# Pengecualian Neptunus OpenCypher
<a name="access-graph-opencypher-exceptions"></a>

Saat bekerja dengan OpenCypher di Amazon Neptunus, berbagai pengecualian dapat terjadi. Di bawah ini adalah pengecualian umum yang mungkin Anda terima, baik dari titik akhir HTTPS atau dari driver Bolt (semua pengecualian dari driver Bolt dilaporkan sebagai Pengecualian Status Server):


| Kode HTTP | Pesan kesalahan | Dapat diambil? | Tindakan Perbaikan | 
| --- | --- | --- | --- | 
| 400 | *(kesalahan sintaks, disebarkan langsung dari parser OpenCypher)* | Tidak | Perbaiki sintaks kueri, lalu coba lagi. | 
| 500 | `Operation terminated (out of memory)` | Ya | Ulangi kueri untuk menambahkan kriteria penyaringan tambahan untuk mengurangi memori yang diperlukan | 
| 500 | Operasi dihentikan (batas waktu terlampaui) | Ya | Tingkatkan batas waktu kueri di grup parameter cluster DB, atau [coba lagi permintaannya](https://docs.aws.amazon.com/general/latest/gr/api-retries.html). | 
| 500 | Operasi dihentikan (dibatalkan oleh pengguna) | Ya | Coba lagi permintaannya. | 
| 500 | Reset basis data sedang berlangsung. Silakan coba lagi kueri setelah klaster tersedia. | Ya | Coba lagi ketika reset selesai. | 
| 500 | Operasi gagal karena operasi bersamaan yang bertentangan (silakan coba lagi). Transaksi saat ini bergulir kembali. | Ya | Coba lagi menggunakan strategi [backoff dan coba lagi eksponensial](best-practices-opencypher-retry-logic.md). | 
| 400 | *(operation name)* operation/feature Pengecualian tidak didukung | Tidak | Operasi yang ditentukan tidak didukung. | 
| 400 | Pembaruan OpenCypher dicoba pada replika hanya-baca | Tidak | Ubah titik akhir target ke titik akhir penulis. | 
| 400 | MalformedQueryException (Neptunus tidak menunjukkan status parser internal) | Tidak | Sintaks kueri yang benar dan coba lagi. | 
| 400 | Tidak dapat menghapus node, karena masih memiliki hubungan. Untuk menghapus node ini, Anda harus terlebih dahulu menghapus hubungannya. | Tidak | Alih-alih menggunakan `MATCH (n) DELETE n` penggunaan `MATCH(n) DETACH DELETE(n)` | 
| 400 | Operasi tidak valid: mencoba menghapus label terakhir dari sebuah node. Sebuah node harus memiliki setidaknya satu label. | Tidak | Neptunus mengharuskan semua node memiliki setidaknya satu label, dan jika node dibuat tanpa label eksplisit, label default ditetapkan. `vertex` Ubah logika and/or aplikasi kueri agar tidak menghapus label terakhir. Label tunggal dari sebuah node dapat diperbarui dengan menetapkan label baru dan kemudian menghapus label lama. | 
| 500 | Jumlah maksimum permintaan telah dilanggar, ConfiguredQueueCapacity = \$1\$1 untuk ConnID = \$1\$1 | Ya | Saat ini hanya 8.192 permintaan bersamaan yang dapat diproses, terlepas dari tumpukan dan protokolnya. | 
| 500 | Batas koneksi maks dilanggar. | Ya | Hanya 1000 koneksi Bolt bersamaan per instance yang diizinkan (untuk HTTP tidak ada batasan). | 
| 400 | Diharapkan [salah satu dari: Node, Relationship or Path] dan mendapat Literal | Tidak | Periksa apakah Anda meneruskan argumen yang benar, sintaks kueri yang benar, dan coba lagi. | 
| 400 | Nilai properti harus literal sederhana. Atau: Peta yang Diharapkan untuk properti Set tetapi tidak menemukannya. | Tidak | Klausa SET hanya menerima literal sederhana, bukan tipe komposit. | 
| 400 | Entitas yang ditemukan lolos untuk penghapusan tidak ditemukan | Tidak | Periksa apakah entitas yang Anda coba hapus ada di database.  | 
| 400 | Pengguna tidak memiliki akses ke database. | Tidak | Periksa kebijakan tentang peran IAM yang digunakan. | 
| 400 | Tidak ada token yang dilewatkan sebagai bagian dari permintaan | Tidak | Token yang ditandatangani dengan benar harus diteruskan sebagai bagian dari permintaan kueri pada cluster yang diaktifkan IAM. | 
| 400 | Pesan kesalahan disebarkan. | Tidak | Hubungi AWS Support dengan ID Permintaan. | 
| 500 | Operasi dihentikan (kesalahan internal) | Ya | Hubungi AWS Support dengan ID Permintaan. | 

# Ekstensi OpenCypher di Amazon Neptunus
<a name="access-graph-opencypher-extensions"></a>

 Amazon Neptunus mendukung referensi spesifikasi OpenCypher versi 9. Silakan lihat [Kepatuhan spesifikasi OpenCypher di Amazon Neptunus](feature-opencypher-compliance.md) di Amazon Neptunus untuk detailnya. Selain itu, Amazon Neptunus mendukung fitur yang tercantum di sini. Kecuali versi tertentu disebutkan, fitur-fiturnya tersedia di Database Neptunus dan Neptunus Analytics. 

## Akses data S3 waktu kueri
<a name="opencypher-compliance-neptune-read"></a>

Tersedia dalam Database Neptunus 1.4.7.0 dan yang lebih tinggi.

Neptunus mendukung `neptune.read()` fungsi untuk membaca data CSV atau Parket dari Amazon S3 langsung dalam kueri OpenCypher. Tidak seperti pemuat massal yang mengimpor data sebelum melakukan kueri, `neptune.read()` mengakses data Amazon S3 pada waktu eksekusi kueri.

Untuk dokumentasi lengkap, lihat[neptune.read ()](access-graph-opencypher-21-extensions-s3-read.md).

## Fungsi khusus Neptunus `join()`
<a name="opencypher-compliance-join-function"></a>

Tersedia dalam Database Neptunus dan Neptunus Analytics.

Neptunus mengimplementasikan fungsi `join()` yang tidak ada dalam spesifikasi OpenCypher. Ini menciptakan string literal dari daftar literal string dan pembatas string. Dibutuhkan dua argumen:
+ Argumen pertama adalah daftar literal string.
+ Argumen kedua adalah string pembatas, yang dapat terdiri dari nol, satu, atau lebih dari satu karakter.

Contoh:

```
join(["abc", "def", "ghi"], ", ")    // Returns "abc, def, ghi"
```

## Fungsi khusus Neptunus `removeKeyFromMap()`
<a name="opencypher-compliance-removeKeyFromMap-function"></a>

Tersedia dalam Database Neptunus dan Neptunus Analytics.

Neptunus mengimplementasikan fungsi `removeKeyFromMap()` yang tidak ada dalam spesifikasi OpenCypher. Ini menghapus kunci tertentu dari peta dan mengembalikan peta baru yang dihasilkan.

Fungsi ini membutuhkan dua argumen:
+ Argumen pertama adalah peta untuk menghapus kunci.
+ Argumen kedua adalah kunci untuk menghapus dari peta.

`removeKeyFromMap()`Fungsi ini sangat berguna dalam situasi di mana Anda ingin menetapkan nilai untuk node atau hubungan dengan membuka daftar peta. Contoh:

```
UNWIND [{`~id`: 'id1', name: 'john'}, {`~id`: 'id2', name: 'jim'}] as val
CREATE (n {`~id`: val.`~id`})
SET n = removeKeyFromMap(val, '~id')
```

## Nilai ID kustom untuk properti node dan hubungan
<a name="opencypher-compliance-custom-ids"></a>

Tersedia dalam Database Neptunus 1.2.0.2 dan lebih tinggi, dan Neptunus Analytics.

Mulai [rilis mesin 1.2.0.2](engine-releases-1.2.0.2.md), Neptunus telah memperluas spesifikasi OpenCypher sehingga Anda sekarang dapat menentukan `id` nilai untuk node dan hubungan di,, dan klausa. `CREATE` `MERGE` `MATCH` Ini memungkinkan Anda menetapkan string yang ramah pengguna alih-alih yang dihasilkan sistem untuk mengidentifikasi node dan hubungan UUIDs .

Di Neptunus Analytics, nilai id kustom tidak tersedia untuk tepi.

**Awas**  
Ekstensi ke spesifikasi OpenCypher ini tidak kompatibel ke belakang, karena sekarang `~id` dianggap sebagai nama properti yang dicadangkan. Jika Anda sudah menggunakan `~id` sebagai properti dalam data dan kueri, Anda harus memigrasikan properti yang ada ke kunci properti baru dan menghapus yang lama. Lihat [Apa yang harus dilakukan jika Anda saat ini menggunakan `~id` sebagai properti](#opencypher-compliance-custom-ids-migrating).

Berikut adalah contoh yang menunjukkan cara membuat node dan relasi yang memiliki ID kustom:

```
CREATE (n {`~id`: 'fromNode', name: 'john'})
  -[:knows {`~id`: 'john-knows->jim', since: 2020}]
  ->(m {`~id`: 'toNode', name: 'jim'})
```

Jika Anda mencoba membuat ID kustom yang sudah digunakan, Neptunus akan membuat kesalahan. `DuplicateDataException`

Berikut adalah contoh penggunaan ID kustom dalam `MATCH` klausa:

```
MATCH (n {`~id`: 'id1'})
RETURN n
```

Berikut adalah contoh penggunaan kustom IDs dalam `MERGE` klausa:

```
MATCH (n {name: 'john'}), (m {name: 'jim'})
MERGE (n)-[r {`~id`: 'john->jim'}]->(m)
RETURN r
```

### Apa yang harus dilakukan jika Anda saat ini menggunakan `~id` sebagai properti
<a name="opencypher-compliance-custom-ids-migrating"></a>

Dengan [rilis mesin 1.2.0.2](engine-releases-1.2.0.2.md), `~id` kunci dalam klausa OpenCypher sekarang diperlakukan sebagai pengganti sebagai properti. `id` Ini berarti bahwa jika Anda memiliki properti bernama`~id`, mengaksesnya menjadi tidak mungkin.

Jika Anda menggunakan `~id` properti, yang harus Anda lakukan sebelum memutakhirkan ke rilis mesin `1.2.0.2` atau di atasnya adalah terlebih dahulu memigrasikan `~id` properti yang ada ke kunci properti baru, lalu menghapus properti tersebut`~id`. Misalnya, kueri di bawah ini:
+ Menciptakan properti baru bernama 'NewId' untuk semua node,
+ menyalin nilai properti '\$1id' ke properti 'NewId',
+ dan menghapus properti '\$1id' dari data

```
MATCH (n)
WHERE exists(n.`~id`)
SET n.newId = n.`~id`
REMOVE n.`~id`
```

Hal yang sama perlu dilakukan untuk setiap hubungan dalam data yang memiliki `~id` properti.

Anda juga harus mengubah kueri apa pun yang Anda gunakan sebagai referensi `~id` properti. Misalnya, kueri ini:

```
MATCH (n)
WHERE n.`~id` = 'some-value'
RETURN n
```

... akan berubah menjadi ini:

```
MATCH (n)
WHERE n.newId = 'some-value'
RETURN n
```

## Dukungan subquery CALL di Neptunus
<a name="call-subquery-support"></a>

 Tersedia dalam Database Neptunus 1.4.1.0 dan lebih tinggi, dan Neptunus Analytics. 

 Amazon Neptunus mendukung subkueri`CALL`. `CALL`Subquery adalah bagian dari query utama yang berjalan dalam lingkup terisolasi untuk setiap input ke `CALL` subquery. 

 Misalnya, grafik berisi data tentang orang, teman mereka, dan kota tempat mereka tinggal. Kita dapat mengambil dua kota terbesar tempat setiap teman seseorang tinggal dengan menggunakan `CALL` subquery: 

```
MATCH (person:Person)-[:knows]->(friend) 
CALL { 
  WITH friend 
  MATCH (friend)-[:lived_in]->(city) 
  RETURN city 
  ORDER BY city.population DESC
  LIMIT 2 
} 
RETURN person, friend, city
```

 Dalam contoh ini, bagian kueri di dalam `CALL { ... }` dijalankan untuk masing-masing `friend` yang dicocokkan dengan klausa MATCH sebelumnya. Ketika kueri batin dijalankan, `LIMIT` klausa `ORDER` dan bersifat lokal di kota-kota tempat seorang teman tertentu tinggal, jadi kami memperoleh (paling banyak) dua kota per teman. 

 Semua klausa kueri tersedia di dalam `CALL` subkueri. Ini termasuk `CALL` subquery bersarang juga. Beberapa batasan untuk `WITH` klausa pertama dan variabel yang dipancarkan ada dan dijelaskan di bawah ini. 

### Lingkup variabel di dalam subquery CALL
<a name="variable-scope-inside-call-subquery"></a>

 Variabel dari klausa sebelum `CALL` subquery yang digunakan di dalamnya harus diimpor oleh klausa awal. `WITH` Tidak seperti `WITH` klausa reguler hanya dapat berisi daftar variabel tetapi tidak mengizinkan aliasing dan tidak dapat digunakan bersama dengan`DISTINCT`,,, `ORDER BY``WHERE`, `SKIP` atau. `LIMIT` 

### Variabel dikembalikan dari CALL subquery
<a name="variables-returned-call-subquery"></a>

 Variabel yang dipancarkan dari `CALL` subquery ditentukan dengan klausa akhir. `RETURN` Perhatikan bahwa variabel yang dipancarkan tidak dapat tumpang tindih dengan variabel sebelum subquery. `CALL` 

### Batasan
<a name="call-subquery-limitations"></a>

 Sampai sekarang, pembaruan di dalam `CALL` subquery tidak didukung. 

## Fungsi Neptunus OpenCypher
<a name="opencypher-compliance-new-functions"></a>

 Tersedia dalam Database Neptunus 1.4.1.0 dan lebih tinggi, dan Neptunus Analytics. 

**textIndexOf**

 `textIndexOf(text :: STRING, lookup :: STRING, from = 0 :: INTEGER?, to = -1 :: INTEGER?) :: (INTEGER?)` 

 Mengembalikan indeks kejadian pertama `lookup` dalam kisaran `text` mulai dari offset `from` (inklusif), melalui offset `to` (eksklusif). Jika `to` -1, rentang berlanjut hingga akhir`text`. Pengindeksan berbasis nol, dan dinyatakan dalam nilai skalar Unicode (poin kode non-pengganti). 

```
RETURN textIndexOf('Amazon Neptune', 'e')
{
  "results": [{
      "textIndexOf('Amazon Neptune', 'e')": 8
    }]
}
```

**collToSet**

 `collToSet(values :: LIST OF ANY?) :: (LIST? OF ANY?)` 

 Mengembalikan daftar baru yang hanya berisi elemen unik dari daftar asli. Urutan daftar asli **dipertahankan** (misalnya `[1, 6, 5, 1, 5]` pengembalian`[1, 6, 5]`). 

```
RETURN collToSet([1, 6, 5, 1, 1, 5])
{
  "results": [{
      "collToSet([1, 6, 5, 1, 1, 5])": [1, 6, 5]
    }]
}
```

**CollKurangi**

 `collSubtract(first :: LIST OF ANY?, second :: LIST OF ANY?) :: (LIST? OF ANY?)` 

 Mengembalikan daftar baru yang berisi semua elemen unik dari `first` mengecualikan elemen dari`second`. 

```
RETURN collSubtract([2, 5, 1, 0], [1, 5])
{
  "results": [{
      "collSubtract([2, 5, 1, 0], [1, 5])": [0, 2]
    }]
}
```

**CollIntersection**

 `collIntersection(first :: LIST? OF ANY?, second :: LIST? OF ANY?) :: (LIST? OF ANY?)` 

 Mengembalikan daftar baru yang berisi semua elemen unik dari persimpangan `first` dan`second`. 

```
RETURN collIntersection([2, 5, 1, 0], [1, 5])
{
  "results": [{
      "collIntersection([2, 5, 1, 0], [1, 5])": [1, 5]
    }]
}
```

## Fungsi penyortiran
<a name="sorting-functions"></a>

 Bagian berikut mendefinisikan fungsi untuk mengurutkan koleksi. Fungsi-fungsi ini mengambil (dalam beberapa kasus opsional) argumen `config` peta, atau daftar beberapa peta semacam itu, yang menentukan kunci pengurutan arah and/or pengurutan: 

```
{ key: STRING, order: STRING }
```

 Berikut `key` adalah properti map atau node yang nilainya akan digunakan untuk menyortir. `order`adalah "`asc`" atau "`desc`" (case insensitive) untuk menentukan jenis naik atau turun, masing-masing. Secara default, penyortiran akan dilakukan dalam urutan menaik. 

**CollSort**

 `collSort(coll :: LIST OF ANY, config :: MAP?) :: (LIST? OF ANY?)` 

 Mengembalikan daftar diurutkan baru yang berisi unsur-unsur dari daftar `coll` masukan. 

```
RETURN collSort([5, 3, 1], {order: 'asc'})
{
  "results": [{
      "collSort([5, 3, 1])": [1, 3, 5]
    }]
}
```

**collSortMaps**

 `collSortMaps(coll :: LIST OF MAP, config :: MAP) :: (LIST? OF ANY?)` 

 Mengembalikan daftar peta diurutkan berdasarkan nilai `key` properti tertentu. 

```
RETURN collSortMaps([{name: 'Alice', age: 25}, {name: 'Bob', age: 35}, {name: 'Charlie', age: 18}], {key: 'age', order: 'desc'})
{
  "results": [{
      "x": [{
          "age": 35,
          "name": "Bob"
        }, {
          "age": 25,
          "name": "Alice"
        }, {
          "age": 18,
          "name": "Charlie"
        }]
    }]
}
```

**collSortMulti**

```
collSortMulti(coll :: LIST OF MAP?, 
configs = [] :: LIST OF MAP, 
limit = -1 :: INTEGER?, 
skip = 0 :: INTEGER?) :: (LIST? OF ANY?)
```

 Mengembalikan daftar peta diurutkan berdasarkan nilai `key` properti tertentu, opsional menerapkan batas dan lewati. 

```
RETURN collSortMulti([{name: 'Alice', age: 25}, {name: 'Bob', age: 35}, {name: 'Charlie', age: 18}], [{key: 'age', order: 'desc'}, {key:'name'}]) as x
{
  "results": [{
      "x": [{
          "age": 35,
          "name": "Bob"
        }, {
          "age": 25,
          "name": "Alice"
        }, {
          "age": 18,
          "name": "Charlie"
        }]
    }]
}
```

**collSortNodes**

 `collSortNodes(coll :: LIST OF NODE, config :: MAP) :: (LIST? OF NODE?)` 

 Mengembalikan versi diurutkan dari daftar `coll` masukan, mengurutkan elemen node dengan nilai-nilai `key` properti masing-masing. 

```
create (n:person {name: 'Alice', age: 23}), (m:person {name: 'Eve', age: 21}), (o:person {name:'Bob', age:25})
{"results":[]}

match (n:person) with collect(n) as people return collSortNodes(people, {key: 'name', order: 'desc'})
{
  "results": [{
      "collSortNodes(people, 'name')": [{
          "~id": "e599240a-8c23-4337-8aa8-f603c8fb5488",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 21,
            "name": "Eve"
          }
        }, {
          "~id": "8a6ef785-59e3-4a0b-a0ff-389655a9c4e6",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 25,
            "name": "Bob"
          }
        }, {
          "~id": "466bc826-f47f-452c-8a27-6b7bdf7ae9b4",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 23,
            "name": "Alice"
          }
        }]
    }]
}

match (n:person) with collect(n) as people return collSortNodes(people, {key: 'age'})
{
  "results": [{
      "collSortNodes(people, '^age')": [{
          "~id": "e599240a-8c23-4337-8aa8-f603c8fb5488",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 21,
            "name": "Eve"
          }
        }, {
          "~id": "466bc826-f47f-452c-8a27-6b7bdf7ae9b4",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 23,
            "name": "Alice"
          }
        }, {
          "~id": "8a6ef785-59e3-4a0b-a0ff-389655a9c4e6",
          "~entityType": "node",
          "~labels": ["person"],
          "~properties": {
            "age": 25,
            "name": "Bob"
          }
        }]
    }]
}
```

## Fungsi temporal
<a name="temporal-functions"></a>

 Fungsi temporal tersedia dari Neptunus [versi](https://docs.aws.amazon.com/releases/release-1.4.5.0.xml) 1.4.5.0 dan yang lebih tinggi. 

### hari
<a name="temporal-functions-day"></a>

 `day(temporal :: (datetime | date)) :: (LONG)` 

 `day`Mengembalikan bulan dari `date` nilai `datetime` atau. Untuk`datetime`: nilai dinormalisasi ke UTC berdasarkan input sebelum mengekstraksi hari. Untuk`date`: hari diekstraksi berdasarkan zona waktu. 

 `datetime`Masukan tersedia di Database Neptunus dan Neptunus Analytics: 

```
RETURN day(datetime('2021-06-03T01:48:14Z'))
{
  "results": [{
      "day(datetime('2021-06-03T01:48:14Z'))": 3
    }]
}
```

 Di sini, `datetime` dinormalisasi ke UTC, jadi \$1 08:00 bergeser kembali ke 2 Juni. 

```
RETURN day(datetime('2021-06-03T00:00:00+08:00'))
{
  "results": [{
      "day(datetime('2021-06-03T00:00:00+08:00'))": 2
    }]
}
```

 `date`Masukan hanya tersedia di Neptunus Analytics: 

```
RETURN day(date('2021-06-03Z'))
{
  "results": [{
      "day(date('2021-06-03Z'))": 3
    }]
}
```

 Zona waktu `date` mempertahankan, menjaga 3 Juni. 

```
RETURN day(date('2021-06-03+08:00'))
{
  "results": [{
      "day(date('2021-06-03+08:00'))": 3
    }]
}
```

### bulan
<a name="temporal-functions-month"></a>

 `month(temporal :: (datetime | date)) :: (LONG)` 

 Mengembalikan bulan dari `date` nilai `datetime` atau (1-12). Untuk`datetime`: nilai dinormalisasi ke UTC berdasarkan input sebelum mengekstraksi bulan. Untuk`date`: bulan diekstraksi berdasarkan zona waktu. 

 `datetime`Masukan tersedia di Database Neptunus dan Neptunus Analytics: 

```
RETURN month(datetime('2021-06-03T01:48:14Z'))
{
  "results": [{
      "month(datetime('2021-06-03T01:48:14Z'))": 6
    }]
}
```

 Di sini, `datetime` dinormalisasi ke UTC, jadi \$1 08:00 bergeser kembali ke 31 Mei. 

```
RETURN month(datetime('2021-06-01T00:00:00+08:00'))
{
  "results": [{
      "month(datetime('2021-06-01T00:00:00+08:00'))": 5
    }]
}
```

 `date`Masukan hanya tersedia di Neptunus Analytics: 

```
RETURN month(date('2021-06-03Z'))
{
  "results": [{
      "month(date('2021-06-03Z'))": 6
    }]
}
```

 Zona waktu `date` mempertahankan, menjaga 1 Juni. 

```
RETURN month(date('2021-06-01+08:00'))
{
  "results": [{
      "month(date('2021-06-01+08:00'))": 6
    }]
}
```

### tahun
<a name="temporal-functions-year"></a>

 `year(temporal :: (datetime | date)) :: (LONG)` 

 Mengembalikan tahun dari `date` nilai `datetime` atau. Untuk`datetime`: nilai dinormalisasi ke UTC berdasarkan input sebelum mengekstraksi tahun. Untuk`date`: tahun diekstraksi berdasarkan zona waktu. 

 `datetime`Masukan tersedia di Database Neptunus dan Neptunus Analytics: 

```
RETURN year(datetime('2021-06-03T01:48:14Z'))
{
  "results": [{
      "year(datetime('2021-06-03T01:48:14Z'))": 2021
    }]
}
```

 Di sini, `datetime` dinormalisasi ke UTC, jadi \$1 08:00 bergeser kembali ke 31 Desember 2020. 

```
RETURN year(datetime('2021-01-01T00:00:00+08:00'))
{
  "results": [{
      "year(datetime('2021-01-01T00:00:00+08:00'))": 2020
    }]
}
```

 `date`Masukan hanya tersedia di Neptunus Analytics: 

```
RETURN year(date('2021-06-03Z'))
{
  "results": [{
      "year(date('2021-06-03Z'))": 2021
    }]
}
```

 Zona waktu `date` mempertahankan, menjaga Juni 2021. 

```
RETURN year(date('2021-01-01+08:00'))
{
  "results": [{
      "year(date('2021-01-01+08:00'))": 2021
    }]
}
```

### Fungsi Neptunus OpenCypher
<a name="openCypher-functions"></a>

 Tersedia dalam Database Neptunus 1.4.6.0 dan lebih tinggi, dan Neptunus Analytics. 

#### mengurangi ()
<a name="openCypher-functions-reduce"></a>

 Mengurangi proses secara berurutan setiap elemen daftar dengan menggabungkannya dengan total berjalan atau 'akumulator.' Dimulai dengan nilai awal, ia memperbarui akumulator setelah setiap operasi dan menggunakan nilai yang diperbarui dalam iterasi berikutnya. 

 `for i in (0, ..., n) acc = acc X list[I], where X denotes any binary operator` 

 Setelah semua elemen diproses, ia mengembalikan hasil akumulasi akhir. 

 Struktur reduce () yang khas adalah - `reduce(accumulator = initial , variable IN list | expression)` 

**Spesifikasi jenis:**  
 `- initial: starting value for the accumulator :: (Long | FLOAT | STRING | LIST? OF (STRING, LONG, FLOAT)) - list: the input list :: LIST OF T where T matches initial type - variable :: represents each element in the input list - expression :: Only supports '+' and '*' operator - return :: Same type as initial ` 

**Pembatasan:**  
 Saat ini, `reduce()` ekspresi hanya mendukung: 
+  Perkalian Numerik 
+  Penambahan Numerik 
+  Penggabungan String 
+  Daftar Penggabungan 

 Mereka diwakili oleh `*` operator `+` atau. Ekspresi harus berupa ekspresi biner seperti yang ditentukan di bawah ini - `expression pattern: accumulator + any variable or accumulator * any variable` 

**Penanganan luapan:**  
 Neptunus mendeteksi luapan numerik selama evaluasi dan merespons `reduce()` secara berbeda berdasarkan tipe data: 

```
LONG (signed 64‑bit)
--------------------
• Valid range: –9 223 372 036 854 775 808 … 9 223 372 036 854 775 807  
• If any intermediate or final value falls outside this range,
  Neptune aborts the query with long overflow error message.
  
FLOAT (IEEE‑754 double)
-----------------------
• Largest finite value ≈ 1.79 × 10^308  
• Larger results overflow to INF
  Once `INF` is produced, it propagates through the remainder
  of the reduction.
```

**Contoh:**  
Lihat contoh berikut untuk fungsi reduce ().

```
1. Long Addition:
RETURN reduce(sum = 0, n IN [1, 2, 3] | sum + n)
{
  "results": [{
      "reduce(sum = 0, n IN [1, 2, 3] | sum + n)": 6
    }]
}

2. String Concatenation:
RETURN reduce(str = "", x IN ["A", "B", "C"] | str + x) 
{
  "results": [{
      "reduce(str = "", x IN ["A", "B", "C"] | str + x)": "ABC"
    }]
}

3. List Combination:
RETURN reduce(lst = [], x IN [1, 2, 3] | lst + x)
{
  "results": [{
      "reduce(lst = [], x IN [1, 2, 3] | lst + x)": [1, 2, 3]
    }]
}

4. Float Addition:
RETURN reduce(total = 0.0, x IN [1.5, 2.5, 3.5] | total + x) 
{
  "results": [{
      "reduce(total = 0.0, x IN [1.5, 2.5, 3.5] | total + x)": 7.5
    }]
}

5. Long Multiplication:
RETURN reduce(product = 1, n IN [1, 2, 3] | product * n)
{
  "results": [{
      "reduce(product = 0, n IN [1, 2, 3] | product * n)": 6
    }]
}

6. Float Multiplication:
RETURN reduce(product = 1.0, n IN [1.5, 2.5, 3.5] | product * n)
{
  "results": [{
      "reduce(product = 1.0, n IN [1.5, 2.5, 3.5] | product * n)": 13.125
    }]
}

7. Long Overflow (Exception):
RETURN reduce(s = 9223372036854775807, x IN [2, 3] | s * x) AS result
{
"results": [{
    "reduce(s = 9223372036854775807, x IN [2, 3] | s * x) AS result": long overflow
    }]
}

8. Float Overflow:
RETURN reduce(s = 9.0e307, x IN [8.0e307, 1.0e307] | s + x) AS result
{
"results": [{
    "reduce(s = 9.0e307, x IN [8.0e307, 1.0e307] | s + x) AS result": INF
    }]
}
```

# neptune.read ()
<a name="access-graph-opencypher-21-extensions-s3-read"></a>

 Neptunus mendukung `neptune.read` prosedur untuk membaca `CALL` data dari Amazon S3 dan kemudian menjalankan kueri OpenCypher (baca, sisipkan, perbarui) menggunakan data. Prosedur menghasilkan setiap baris dalam file sebagai baris variabel hasil yang dideklarasikan. Ini menggunakan kredensyal IAM dari penelepon untuk mengakses data di Amazon S3. Lihat [Mengelola izin untuk neptune.read ()](access-graph-opencypher-21-extensions-s3-read-permissions.md) untuk mengatur izin. AWS Wilayah bucket Amazon S3 harus berada di wilayah yang sama di mana instance berada. Saat ini, pembacaan lintas wilayah tidak didukung. 

 **Sintaksis** 

```
CALL neptune.read(
  {
    source: "string",
    format: "parquet/csv",
    concurrency: 10
  }
)
YIELD row
...
```

**Masukan**
+  **source** (wajib) - Amazon S3 URI ke **satu** objek. Awalan Amazon S3 ke beberapa objek tidak didukung. 
+  **format** (wajib) - `parquet` dan `csv` didukung. 
  +  Rincian lebih lanjut tentang format Parket yang didukung dapat ditemukan di[Jenis kolom Parket yang didukung](access-graph-opencypher-21-extensions-s3-read-parquet.md#access-graph-opencypher-21-extensions-s3-read-parquet-column-types). 
  +  Untuk informasi selengkapnya tentang format csv yang didukung, lihat[Muat format untuk data OpenCypher](bulk-load-tutorial-format-opencypher.md). 
+  **konkurensi** (opsional) - Jenis: 0 atau bilangan bulat yang lebih besar. Default: 0. Menentukan jumlah thread yang akan digunakan untuk membaca file. Jika nilainya 0, jumlah maksimum utas yang diizinkan oleh sumber daya akan digunakan. Untuk Parket, disarankan untuk diatur ke sejumlah grup baris. 

**Output**

 Neptune.read mengembalikan: 
+  **baris** - Jenis: Peta 
  +  Setiap baris dalam file, di mana kuncinya adalah kolom dan nilainya adalah data yang ditemukan di setiap kolom. 
  +  Anda dapat mengakses data setiap kolom seperti properti access (`row.col`). 

## Praktik terbaik untuk neptune.read ()
<a name="access-graph-opencypher-21-extensions-s3-read-best-practices"></a>

Operasi pembacaan Neptunus S3 bisa intensif memori. Harap gunakan jenis instans yang cocok untuk beban kerja produksi seperti yang diuraikan dalam [Memilih jenis instans untuk Amazon Neptunus](instance-types.md).

Penggunaan memori dan kinerja `neptune.read()` permintaan dipengaruhi oleh berbagai faktor seperti ukuran file, jumlah kolom, jumlah baris, dan format file. Bergantung pada struktur, file kecil (misalnya, file CSV 100MB atau di bawahnya, file Parket 20MB atau di bawahnya) dapat bekerja dengan andal pada sebagian besar jenis instance yang sesuai dengan produksi, sedangkan file yang lebih besar mungkin memerlukan memori substanal yang tidak dapat disediakan oleh tipe instance yang lebih kecil.

Saat menguji fitur ini, disarankan untuk memulai dengan file kecil dan menskalakan secara bertahap untuk memastikan beban kerja baca Anda dapat diakomodasi oleh ukuran instans Anda. Jika Anda melihat `neptune.read()` permintaan yang mengarah ke out-of-memory pengecualian atau instans dimulai ulang, pertimbangkan untuk membagi file Anda menjadi potongan yang lebih kecil, mengurangi kompleksitas file, atau meningkatkan ke jenis instans yang lebih besar.

# Contoh kueri menggunakan parket
<a name="access-graph-opencypher-21-extensions-s3-read-parquet"></a>

Contoh query berikut mengembalikan jumlah baris dalam file Parket tertentu:

```
CALL neptune.read(
  {
    source: "<s3 path>",
    format: "parquet"
  }
)
YIELD row
RETURN count(row)
```

Anda dapat menjalankan contoh query menggunakan `execute-open-cypher-query` operasi di AWS CLI dengan mengeksekusi kode berikut:

```
aws neptunedata execute-open-cypher-query \
--open-cypher-query "CALL neptune.read({source: '<s3 path>', format: 'parquet'}) YIELD row RETURN count(row)" \
--endpoint-url https://my-cluster-name.cluster-abcdefgh1234.us-east-1.neptune.amazonaws.com:8182
```

Kueri bisa fleksibel dalam apa yang dilakukannya dengan baris yang dibaca dari file Parket. Misalnya, kueri berikut membuat simpul dengan bidang yang disetel ke data yang ditemukan di file Parket:

```
CALL neptune.read(
  {
    source: "<s3 path>",
    format: "parquet"
  }
)
YIELD row
CREATE (n {someField: row.someCol}) 
RETURN n
```

**Awas**  
Tidak dianggap praktik yang baik untuk menggunakan klausa penghasil hasil besar seperti `MATCH(n)` sebelum klausa. `CALL` Ini akan mengarah pada kueri yang berjalan lama, karena produk silang antara solusi yang masuk dari klausa sebelumnya dan baris yang dibaca oleh neptune.read. Disarankan untuk memulai kueri dengan `CALL` neptune.read.

## Jenis kolom Parket yang didukung
<a name="access-graph-opencypher-21-extensions-s3-read-parquet-column-types"></a>

**Jenis Data Parket:**
+ NULL
+ BOOLEAN
+ FLOAT
+ DOUBLE
+ STRING
+ INTEGER YANG DITANDATANGANI: UINT8,, UINT16, UINT32 UINT64
+ MAP: Hanya mendukung satu tingkat. Tidak mendukung bersarang.
+ DAFTAR: Hanya mendukung satu tingkat. Tidak mendukung bersarang.

**Tipe data khusus Neptunus:**

Berbeda dengan header kolom properti dari format CSV, header kolom properti dari format Parket hanya perlu memiliki nama properti, jadi tidak perlu memiliki nama tipe atau kardinalitas.

Namun, ada beberapa jenis kolom khusus dalam format Parket yang memerlukan anotasi dalam metadata, termasuk tipe Any, tipe Date, tipe DateTime, dan jenis Geometri. Objek berikut adalah contoh anotasi metadata yang diperlukan untuk file yang berisi kolom jenis khusus ini:

```
"metadata": {
    "anyTypeColumns": ["UserCol1"],
    "dateTypeColumns": ["UserCol2"],
    "dateTimeTypeColumns": ["UserCol3"],
    "geometryTypeColumns": ["UserCol4"]
}
```

Di bawah ini adalah detail tentang muatan yang diharapkan terkait dengan jenis ini:
+ Tipe kolom Any didukung di kolom pengguna. Tipe Any adalah jenis “gula sintaksis” untuk semua jenis lain yang kami dukung. Ini sangat berguna jika kolom pengguna memiliki beberapa jenis di dalamnya. Payload dari nilai tipe Any adalah daftar string json sebagai berikut:`{"value": "10", "type": "Int"};{"value": "1.0", "type": "Float"}`, yang memiliki bidang nilai dan bidang tipe di setiap string json individu. Nilai kardinalitas kolom Any diatur, artinya kolom dapat menerima beberapa nilai. 
  + Neptunus mendukung jenis berikut dalam tipe Any: Bool (atau Boolean), Byte, Short, Int, Long,,,,, Float, Double UnsignedByte UnsignedShort, Date UnsignedInt UnsignedLong, DateTime, String, dan Geometry.
  + Jenis vektor tidak didukung dalam Tipe apa pun.
  + Bersarang Tipe apa pun tidak didukung. Misalnya, `{"value": {"value": "10", "type": "Int"}, "type": "Any"}`.
+ Kolom tipe Tanggal dan Datetime didukung di kolom pengguna. Muatan kolom ini harus disediakan sebagai string mengikuti format XSD atau salah satu format di bawah ini: 
  + YYYY-MM-DD
  + YYYY-MM-DDTHH: mm
  + YYYY-MM-DDTHH: MM: SS
  + YYYY-MM-DDTHH: mm: SSZ
  + YYYY-MM-DDTHH: MM: SS.SSSZ
  + YYYY-MM-DDTHH: mm: SS [\$1\$1-] hhmm
  + YYYY-MM-DDTHH: mm: SS.sss [\$1\$1-] hhmm
+ Jenis kolom Geometri didukung di kolom pengguna. Muatan kolom ini hanya boleh berisi geometri primitif tipe Point, disediakan sebagai string dalam format teks terkenal (WKT). Misalnya, POINT (30 10) akan menjadi nilai Geometri yang valid.

## Contoh keluaran parket
<a name="sample-parquet-output"></a>

Diberikan file Parket seperti ini:

```
<s3 path>

Parquet Type:
    int8     int16       int32             int64              float      double    string
+--------+---------+-------------+----------------------+------------+------------+----------+
|   Byte |   Short |       Int   |                Long  |     Float  |    Double  | String   |
|--------+---------+-------------+----------------------+------------+------------+----------|
|   -128 |  -32768 | -2147483648 | -9223372036854775808 |    1.23456 |    1.23457 | first    |
|    127 |   32767 |  2147483647 |  9223372036854775807 |  nan       |  nan       | second   |
|      0 |       0 |           0 |                    0 | -inf       | -inf       | third    |
|      0 |       0 |           0 |                    0 |  inf       |  inf       | fourth   |
+--------+---------+-------------+----------------------+------------+------------+----------+
```

Berikut adalah contoh output yang dikembalikan oleh neptune.read menggunakan query berikut:

```
aws neptunedata execute-open-cypher-query \
--open-cypher-query "CALL neptune.read({source: '<s3 path>', format: 'parquet'}) YIELD row RETURN row" \
--endpoint-url https://my-cluster-name.cluster-abcdefgh1234.us-east-1.neptune.amazonaws.com:8182
```

```
{
 "results": [{
 "row": {
 "Float": 1.23456,
 "Byte": -128,
 "Int": -2147483648,
 "Long": -9223372036854775808,
 "String": "first",
 "Short": -32768,
 "Double": 1.2345678899999999
 }
 }, {
 "row": {
 "Float": "NaN",
 "Byte": 127,
 "Int": 2147483647,
 "Long": 9223372036854775807,
 "String": "second",
 "Short": 32767,
 "Double": "NaN"
 }
 }, {
 "row": {
 "Float": "-INF",
 "Byte": 0,
 "Int": 0,
 "Long": 0,
 "String": "third",
 "Short": 0,
 "Double": "-INF"
 }
 }, {
 "row": {
 "Float": "INF",
 "Byte": 0,
 "Int": 0,
 "Long": 0,
 "String": "fourth",
 "Short": 0,
 "Double": "INF"
 }
 }]
}
```

Saat ini, tidak ada cara untuk mengatur node atau label tepi ke bidang data yang berasal dari file Parket. Disarankan agar Anda mempartisi kueri menjadi beberapa kueri, satu untuk setiap label/jenis.

```
CALL neptune.read({source: '<s3 path>', format: 'parquet'})
 YIELD row 
WHERE row.`~label` = 'airport'
CREATE (n:airport)

CALL neptune.read({source: '<s3 path>', format: 'parquet'})
YIELD row 
WHERE row.`~label` = 'country'
CREATE (n:country)
```

# Contoh kueri menggunakan CSV
<a name="access-graph-opencypher-21-extensions-s3-read-csv"></a>

Dalam contoh ini, kueri mengembalikan jumlah baris dalam file CSV yang diberikan:

```
CALL neptune.read(
  {
    source: "<s3 path>",
    format: "csv"
  }
)
YIELD row
RETURN count(row)
```

Anda dapat menjalankan contoh query menggunakan execute-open-cypher-query operasi di AWS CLI dengan mengeksekusi kode berikut:

```
aws neptunedata execute-open-cypher-query \
--open-cypher-query "CALL neptune.read({source: '<s3 path>', format: 'csv'}) YIELD row RETURN count(row)" \
--endpoint-url https://my-cluster-name.cluster-abcdefgh1234.us-east-1.neptune.amazonaws.com:8182
```

Kueri bisa fleksibel dalam apa yang dilakukannya dengan baris yang dibaca dari file CSV. Misalnya, kueri berikut membuat simpul dengan bidang yang disetel ke data dari file CSV:

```
CALL neptune.read(
  {
    source: "<s3 path>",
    format: "csv"
  }
)
YIELD row
CREATE (n {someField: row.someCol}) 
RETURN n
```

**Awas**  
Ini tidak dianggap praktik yang baik menggunakan klausa penghasil hasil besar seperti MATCH (n) sebelum klausa CALL. Ini akan mengarah pada kueri yang berjalan lama karena produk silang antara solusi yang masuk dari klausa sebelumnya dan baris yang dibaca oleh neptune.read. Disarankan untuk memulai kueri dengan CALL neptune.read.

## Header kolom properti
<a name="property-column-headers"></a>

Anda dapat menentukan kolom (`:`) untuk properti dengan menggunakan sintaks berikut. Nama jenis tidak peka dengan huruf besar/kecil. Jika titik dua muncul dalam nama properti, itu harus diloloskan dengan mendahuluinya dengan garis miring terbalik:. `\:`

```
propertyname:type
```

**catatan**  
Spasi, koma, carriage return, dan karakter baris baru tidak diperbolehkan di header kolom, sehingga nama properti tidak dapat menyertakan karakter ini.
Anda dapat menentukan kolom untuk jenis array dengan menambahkan `[]` ke jenisnya:  

  ```
                          propertyname:type[]
  ```
Properti edge hanya dapat memiliki satu nilai dan akan menyebabkan kesalahan jika jenis array yang ditentukan atau nilai kedua ditentukan. Contoh berikut menunjukkan header kolom untuk properti bernama umur tipe Int:  

  ```
  age:Int
  ```

Setiap baris dalam file akan perlu memiliki integer dalam posisi itu atau dibiarkan kosong. Array string diperbolehkan, tetapi string dalam array tidak dapat menyertakan karakter titik koma () kecuali jika diloloskan menggunakan garis miring terbalik (`;`). `\;`

## Jenis kolom CSV yang didukung
<a name="supported-csv-column-types"></a>
+ **BOOL (atau BOOLEAN)** - Nilai yang diizinkan: benar, salah. Menunjukkan bidang Boolean. Nilai apa pun selain true akan diperlakukan sebagai false.
+ **FLOAT** - Rentang: 32-bit IEEE 754 floating point termasuk Infinity, INF, -Infinity, -INF dan NaN (). not-a-number
+ **DOUBLE** - Rentang: 64-bit IEEE 754 floating point termasuk Infinity, INF, -Infinity, -INF dan NaN (). not-a-number
+ **TALI** - 
  + Tanda kutip adalah opsional. Karakter koma, baris baru, dan carriage return secara otomatis lolos jika disertakan dalam string yang dikelilingi oleh tanda kutip ganda (“). Contoh: “Halo, Dunia”.
  + Untuk menyertakan tanda kutip dalam string yang dikutip, Anda dapat menghindari tanda kutip dengan menggunakan dua berturut-turut: Contoh: “Halo “" Dunia ""”.
  + Array string diperbolehkan, tetapi string dalam array tidak dapat menyertakan karakter titik koma (;) kecuali jika diloloskan menggunakan garis miring terbalik (\$1;).
  + Jika Anda ingin mengapit string dalam array dengan tanda kutip, Anda harus mengapit keseluruhan array dengan satu set tanda kutip. Contoh: “String satu; String 2; String 3".
+ **DATE, DATETIME** - Nilai datetime dapat diberikan dalam format XSD, atau salah satu format berikut: 
  + YYYY-MM-DD
  + YYYY-MM-DDTHH: mm
  + YYYY-MM-DDTHH: MM: SS
  + YYYY-MM-DDTHH: mm: SSZ
  + YYYY-MM-DDTHH: MM: SS.SSSZ
  + YYYY-MM-DDTHH: mm: SS [\$1\$1-] hhmm
  + YYYY-MM-DDTHH: mm: SS.sss [\$1\$1-] hhmm
+ **INTEGER YANG DITANDATANGANI** - 
  + Byte: -128 hingga 127
  + Pendek: -32768 sampai 32767
  + Int: -2^31 hingga 2 ^ 31-1
  + Panjang: -2 ^ 63 hingga 2 ^ 63-1

**Jenis kolom khusus Neptunus:**
+ Tipe kolom Any didukung di kolom pengguna. Tipe Any adalah jenis “gula sintaksis” untuk semua jenis lain yang kami dukung. Ini sangat berguna jika kolom pengguna memiliki beberapa jenis di dalamnya. Payload dari nilai tipe Any adalah daftar string json sebagai berikut:`{"value": "10", "type": "Int"};{"value": "1.0", "type": "Float"}`, yang memiliki bidang nilai dan bidang tipe di setiap string json individu. Header kolom dari tipe Any adalah PropertyName:Any. Nilai kardinalitas kolom Any diatur, artinya kolom dapat menerima beberapa nilai. 
  + Neptunus mendukung jenis berikut dalam tipe Any: Bool (atau Boolean), Byte, Short, Int, Long,,,,, Float, Double UnsignedByte UnsignedShort, Date UnsignedInt UnsignedLong, DateTime, String, dan Geometry.
  + Jenis vektor tidak didukung dalam Tipe apa pun.
  + Bersarang Tipe apa pun tidak didukung. Misalnya, `{"value": {"value": "10", "type": "Int"}, "type": "Any"}`.
+ Jenis kolom Geometri didukung di kolom pengguna. Muatan kolom ini hanya boleh berisi geometri primitif tipe Point, disediakan sebagai string dalam format teks terkenal (WKT). Misalnya, POINT (30 10) akan menjadi nilai Geometri yang valid.

## Contoh keluaran CSV
<a name="sample-csv-output"></a>

Diberikan file CSV berikut:

```
<s3 path>
colA:byte,colB:short,colC:int,colD:long,colE:float,colF:double,colG:string
-128,-32768,-2147483648,-9223372036854775808,1.23456,1.23457,first
127,32767,2147483647,9223372036854775807,nan,nan,second
0,0,0,0,-inf,-inf,third
0,0,0,0,inf,inf,fourth
```

Contoh ini menunjukkan output yang dikembalikan oleh neptune.read menggunakan query berikut:

```
aws neptunedata execute-open-cypher-query \
--open-cypher-query "CALL neptune.read({source: '<s3 path>', format: 'csv'}) YIELD row RETURN row" \
--endpoint-url https://my-cluster-name.cluster-abcdefgh1234.us-east-1.neptune.amazonaws.com:8182
```

```
{
  "results": [{
      "row": {
        "colD": -9223372036854775808,
        "colC": -2147483648,
        "colE": 1.23456,
        "colB": -32768,
        "colF": 1.2345699999999999,
        "colG": "first",
        "colA": -128
      }
    }, {
      "row": {
        "colD": 9223372036854775807,
        "colC": 2147483647,
        "colE": "NaN",
        "colB": 32767,
        "colF": "NaN",
        "colG": "second",
        "colA": 127
      }
    }, {
      "row": {
        "colD": 0,
        "colC": 0,
        "colE": "-INF",
        "colB": 0,
        "colF": "-INF",
        "colG": "third",
        "colA": 0
      }
    }, {
      "row": {
        "colD": 0,
        "colC": 0,
        "colE": "INF",
        "colB": 0,
        "colF": "INF",
        "colG": "fourth",
        "colA": 0
      }
    }]
}
```

Saat ini, tidak ada cara untuk mengatur label node atau edge ke bidang data yang berasal dari file CSV. Disarankan agar Anda mempartisi kueri menjadi beberapa kueri, satu untuk setiap label/jenis.

```
CALL neptune.read({source: '<s3 path>', format: 'csv'})
 YIELD row 
WHERE row.`~label` = 'airport'
CREATE (n:airport)

CALL neptune.read({source: '<s3 path>', format: 'csv'})
YIELD row 
WHERE row.`~label` = 'country'
CREATE (n:country)
```

# Mengelola izin untuk neptune.read ()
<a name="access-graph-opencypher-21-extensions-s3-read-permissions"></a>

## Kebijakan IAM yang Diperlukan
<a name="access-graph-opencypher-21-extensions-s3-read-permissions-iam"></a>

Untuk menjalankan kueri OpenCypher yang digunakan`neptune.read()`, Anda harus memiliki izin yang sesuai untuk mengakses data dalam database Neptunus Anda. Kueri hanya-baca memerlukan tindakan. `ReadDataViaQuery` Kueri yang memodifikasi data memerlukan `WriteDataViaQuery` penyisipan atau penghapusan`DeleteDataViaQuery`. Contoh di bawah ini memberikan ketiga tindakan pada cluster yang ditentukan.

Selain itu, Anda memerlukan izin untuk mengakses bucket S3 yang berisi file data Anda. Pernyataan kebijakan NepTunes3Access memberikan izin S3 yang diperlukan:
+ **`s3:ListBucket`**: Diperlukan untuk memverifikasi keberadaan bucket dan daftar konten.
+ **`s3:GetObject`**: Diperlukan untuk mengakses objek yang ditentukan sehingga kontennya dapat dibaca untuk integrasi ke dalam kueri OpenCypher.

Jika bucket S3 Anda menggunakan enkripsi sisi server AWS KMS, Anda juga harus memberikan izin KMS. KMSAccess Pernyataan kebijakan Neptunes3 memungkinkan Neptunus untuk mendekripsi data dan menghasilkan kunci data saat mengakses objek S3 terenkripsi. Kondisi ini membatasi operasi KMS untuk permintaan yang berasal dari layanan S3 dan RDS di wilayah Anda.
+ **`kms:Decrypt`**: Diperlukan untuk melakukan dekripsi objek terenkripsi sehingga datanya dapat dibaca oleh Neptunus.
+ **`kms:GenerateDataKey`**: Juga diperlukan oleh S3 API yang digunakan untuk mengambil objek yang akan dibaca.

```
{
  "Sid": "NeptuneQueryAccess",
  "Effect": "Allow",
  "Action": [
      "neptune-db:ReadDataViaQuery",
      "neptune-db:WriteDataViaQuery",
      "neptune-db:DeleteDataViaQuery"
  ],
  "Resource": "arn:aws:neptune-db:<REGION>:<AWS_ACCOUNT_ID>:<CLUSTER_RESOURCE_ID>/*"
},
{
  "Sid": "NeptuneS3Access",
  "Effect": "Allow",
  "Action": [
      "s3:ListBucket",
      "s3:GetObject"
  ],
  "Resource": [
      "arn:aws:s3:::neptune-read-bucket",
      "arn:aws:s3:::neptune-read-bucket/*"
  ]
},
{
  "Sid": "NeptuneS3KMSAccess",
  "Effect": "Allow",
  "Action": [
      "kms:Decrypt",
      "kms:GenerateDataKey"
  ],
  "Resource": "arn:aws:kms:<REGION>:<AWS_ACCOUNT_ID>:key/<KEY_ID>",
  "Condition": {
      "StringEquals": {
        "kms:ViaService": [
            "s3.<REGION>.amazonaws.com",
            "rds.<REGION>.amazonaws.com"
        ]
      }
  }
}
```

## Prasyarat penting
<a name="access-graph-opencypher-21-extensions-s3-read-permissions-prerequisites"></a>

Izin dan prasyarat ini memastikan integrasi data S3 yang aman dan andal ke dalam kueri OpenCypher, sambil mempertahankan kontrol akses yang tepat dan langkah-langkah perlindungan data.
+ **Autentikasi IAM**: Fitur ini hanya didukung untuk cluster Neptunus dengan otentikasi IAM diaktifkan. Lihat [Mengamankan database Amazon Neptunus](security.md) untuk petunjuk terperinci tentang cara membuat dan menyambung ke kluster berkemampuan autentikasi IAM.
+ **Titik akhir VPC**:
  + Titik akhir VPC tipe Gateway untuk Amazon S3 diperlukan untuk memungkinkan Neptunus berkomunikasi dengan Amazon S3.
  + Untuk menggunakan AWS KMS enkripsi kustom dalam kueri, titik akhir VPC tipe antarmuka untuk diperlukan agar AWS KMS Neptunus dapat berkomunikasi dengannya. AWS KMS
  + Untuk petunjuk mendetail tentang cara mengonfigurasi titik akhir ini, lihat [Membuat Titik Akhir VPC Amazon S3](bulk-load-tutorial-IAM.md).

# Data Spasial
<a name="access-graph-opencypher-22-spatial-data"></a>

Amazon Neptunus sekarang mendukung kueri spasial, memungkinkan Anda untuk menyimpan dan menganalisis data geometris dalam grafik Anda. Meskipun umumnya digunakan untuk lokasi geografis (seperti koordinat pada peta), fitur spasial bekerja dengan data dua dimensi di mana posisi dan kedekatan penting. Gunakan fitur ini untuk menjawab pertanyaan seperti “Toko mana yang berada dalam jarak 5 mil dari pelanggan ini?” , “Temukan semua rute pengiriman yang bersinggungan dengan area layanan ini,” atau “Komponen mana dalam denah lantai ini yang tumpang tindih dengan zona HVAC?” Neptunus mengimplementasikan dukungan spasial menggunakan fungsi Tipe Spasial standar industri yang bekerja dengan titik, poligon, dan bentuk geometris lainnya. Anda dapat menyimpan data spasial sebagai properti pada node dan tepi, kemudian menggunakan fungsi spasial untuk menghitung jarak, memeriksa apakah titik berada dalam batas, atau menemukan wilayah yang tumpang tindih, semua dalam kueri OpenCypher Anda.

**Kasus penggunaan umum:**
+ **Aplikasi geografis**: Rekomendasi berbasis lokasi, geofencing, perencanaan rute, dan analisis wilayah
+ **Manajemen fasilitas dan ruang**: Tata letak denah lantai, penempatan peralatan, dan cakupan zona
+ **Topologi jaringan**: Pemetaan infrastruktur fisik, area cakupan, dan batas layanan
+ **Desain dan CAD**: Pemosisian komponen, deteksi tabrakan, dan hubungan spasial dalam desain 2D
+ **Pengembangan game**: Penentuan posisi karakter, deteksi tabrakan, dan perhitungan area-of-effect

Implementasi Jenis Spasial di Amazon Neptunus mengikuti arahan ISO/IEC 13249-3:2016, seperti database lainnya. Yang [Fungsi Spasial](access-graph-opencypher-22-spatial-functions.md) tersedia dalam bahasa query OpenCypher.

## Sistem koordinat
<a name="access-graph-opencypher-22-spatial-data-coordinate-system"></a>

Neptunus memiliki satu Spatial Reference Identifier (SRID) untuk seluruh database. Homogenitas sistem koordinat mengurangi kesalahan pengguna dalam query dan meningkatkan kinerja database. Rilis pertama (1.4.7.0) mendukung sistem koordinat Cartesian, juga disebut sebagai SRID 0.

Implementasi Neptunus dari SRID 0 kompatibel dengan nilai bujur dan lintang. Gunakan `ST_DistanceSpheroid` untuk menghitung jarak berdasarkan WGS84 /SRID 4326.

Implementasi saat ini mendukung penyimpanan koordinat 3 dimensi. Fungsi Spasial saat ini hanya mendukung penggunaan koordinat sumbu x dan y (2 dimensi). Koordinat sumbu z saat ini tidak didukung oleh Fungsi Spasial yang tersedia.

## Menyimpan data lokasi
<a name="storing-spatial-data"></a>

Menyimpan data lokasi pada node dan tepi menggunakan tipe properti Geometry. Buat nilai Geometri dari format Teks Terkenal (WKT), cara standar untuk mewakili bentuk geografis sebagai teks. Misalnya, untuk menyimpan lokasi titik:

```
CREATE (n:airport {code: 'ATL', location: ST_GeomFromText('POINT (-84.4281 33.6367)')})
```

Saat bekerja dengan koordinat geografis, argumen pertama (x) mewakili garis bujur dan argumen kedua (y) mewakili garis lintang. Ini mengikuti urutan koordinat standar yang digunakan dalam database spasial dan standar ISO 19125.

**catatan**  
 Neptunus sekarang mendukung tipe data baru yang disebut “Geometri”. Properti Geometri dari node atau edge dapat dibuat dari string WKT menggunakan fungsi. `ST_GeomFromText`  
Neptunus akan secara otomatis menyimpan data Poin dalam indeks spasial khusus untuk meningkatkan kinerja fungsi Tipe Spasial. Misalnya, `ST_Contains` digunakan untuk menemukan titik-titik dalam poligon dipercepat oleh indeks spasial khusus.  
[Halaman Wikipedia untuk representasi Teks Terkenal dari geometri](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry)

## Memuat data spasial secara massal
<a name="loading-spatial-data-bulk"></a>

Saat memuat data secara massal, tentukan jenis Geometri di header CSV Anda. Neptunus akan mengurai string WKT dan membuat properti Geometri yang sesuai:

```
:ID,:LABEL,code:String,city:String,location:Geometry
21,airport,ATL,Atlanta,POINT (-84.42810059 33.63669968)
32,airport,ANC,Anchorage,POINT (-149.9960022 61.17440033)
43,airport,AUS,Austin,POINT (-97.66989899 30.19449997)
```

Untuk detail format CSV lengkap, lihat Format beban massal [OpenCypher](bulk-load-tutorial-format-opencypher.md).

## Meminta data spasial
<a name="querying-spatial-data"></a>

Contoh kueri berikut menggunakan [dataset rute udara](https://github.com/krlawrence/graph/tree/main/sample-data) untuk menunjukkan cara menggunakan Fungsi Spasial di Neptunus.

Jika data Anda memiliki properti lintang dan bujur yang terpisah alih-alih properti Geometri, Anda dapat mengonversinya menjadi titik pada waktu kueri. Temukan 10 bandara terdekat ke lokasi tertentu:

```
MATCH (a:airport)
WITH a, ST_GeomFromText('POINT (' + a.lon + ' ' + a.lat + ')') AS airportLocation
WITH a, airportLocation, ST_Distance(ST_GeomFromText('POINT (-84.4281 33.6367)'), airportLocation) AS distance
WHERE distance IS NOT NULL
RETURN a.code, a.city, distance
ORDER BY distance ASC
LIMIT 10
```

Jika Anda sudah memiliki lokasi yang disimpan`ST_Point`, Anda dapat menggunakan nilai lokasi tersebut secara langsung:

1. Mengatur properti

   ```
   MATCH (a:airport)
   SET a.location = ST_GeomFromText('POINT (' + a.lon + ' ' + a.lat + ')')
   ```

1. Kueri menggunakan ST\$1Distance:

   ```
   MATCH (a:airport)
   WHERE a.location IS NOT NULL
   WITH a, ST_Distance(ST_GeomFromText('POINT (-84.4281 33.6367)'), a.location) AS distance
   RETURN a.code, a.city, distance
   ORDER BY distance ASC
   LIMIT 10
   ```

### Menggunakan driver Bolt
<a name="querying-spatial-data-bolt"></a>

Sebagian besar metode kueri mengembalikan nilai Geometri sebagai string WKT, yang dapat dibaca manusia. Jika Anda menggunakan driver Bolt, nilai Geometri dikembalikan dalam format WKB (Biner Terkenal) untuk efisiensi. Mengkonversi WKB ke objek Geometri dalam aplikasi Anda:

```
try (Session session = driver.session()) {
    Result result = session.run("MATCH (n:airport {code: 'ATL'}) RETURN n.location as geom");
    
    Record record = result.single();
    byte[] wkbBytes = record.get("geom").asByteArray();
    
    // Convert WKB to Geometry object using JTS library
    WKBReader wkbReader = new WKBReader();
    Geometry geom = wkbReader.read(wkbBytes);
}
```

# Fungsi Spasial
<a name="access-graph-opencypher-22-spatial-functions"></a>

Fungsi spasial berikut tersedia di Neptunus OpenCypher untuk bekerja dengan tipe data geometri:
+ [ST\$1titik](access-graph-opencypher-22-spatial-functions-st-point.md)
+ [ST\$1 GeomFromText](access-graph-opencypher-22-spatial-functions-st-geomfromtext.md)
+ [ST\$1 AsText](access-graph-opencypher-22-spatial-functions-st-astext.md)
+ [ST\$1 GeometryType](access-graph-opencypher-22-spatial-functions-st-geometrytype.md)
+ [ST\$1sama](access-graph-opencypher-22-spatial-functions-st-equals.md)
+ [ST\$1Berisi](access-graph-opencypher-22-spatial-functions-st-contains.md)
+ [ST\$1berpotongan](access-graph-opencypher-22-spatial-functions-st-intersect.md)
+ [ST\$1Jarak](access-graph-opencypher-22-spatial-functions-st-distance.md)
+ [ST\$1 DistanceSpheroid](access-graph-opencypher-22-spatial-functions-st-distancespheroid.md)
+ [ST\$1amplop](access-graph-opencypher-22-spatial-functions-st-envelope.md)
+ [ST\$1Buffer](access-graph-opencypher-22-spatial-functions-st-buffer.md)

# ST\$1titik
<a name="access-graph-opencypher-22-spatial-functions-st-point"></a>

ST\$1point mengembalikan titik dari nilai koordinat masukan.

**Sintaksis**

```
ST_Point(x, y, z)
```

**Argumen**
+ `x`- Nilai tipe data PRESISI GANDA yang mewakili koordinat pertama.
+ `y`- Nilai tipe data PRESISI GANDA yang mewakili koordinat kedua.
+ `z`- (opsional)

**Urutan koordinat**

**Saat bekerja dengan koordinat geografis, argumen pertama (`x`) mewakili **garis bujur** dan argumen kedua (`y`) mewakili garis lintang.** Ini mengikuti urutan koordinat standar yang digunakan dalam database spasial dan standar ISO 19125.

```
// Correct: longitude first, latitude second
ST_Point(-84.4281, 33.6367)  // Atlanta airport

// Incorrect: latitude first, longitude second
ST_Point(33.6367, -84.4281)  // This will return NaN in distance calculations
```

**Rentang koordinat yang valid**

Untuk data geografis, pastikan koordinat berada dalam rentang yang valid:
+ Bujur (`x`): -180 hingga 180
+ Lintang (`y`): -90 hingga 90

Koordinat di luar rentang ini akan kembali `NaN` (Bukan Angka) bila digunakan dengan fungsi perhitungan jarak seperti`ST_DistanceSpheroid`.

**Jenis pengembalian**

GEOMETRI dari titik subtipe

Jika x atau y adalah null, maka null dikembalikan.

**Contoh**

Berikut ini membangun geometri titik dari koordinat masukan.

```
RETURN ST_Point(5.0, 7.0); 
POINT(5 7)
```

# ST\$1 GeomFromText
<a name="access-graph-opencypher-22-spatial-functions-st-geomfromtext"></a>

ST\$1 GeomFromText membangun objek geometri dari representasi teks terkenal (WKT) dari geometri input.

**Sintaksis**

```
ST_GeomFromText(wkt_string)
```

**Argumen**
+ `wkt_string`- Nilai tipe data STRING yang merupakan representasi WKT dari geometri.

**Jenis pengembalian**

GEOMETRY

Jika wkt\$1string adalah null, maka null dikembalikan.

Jika wkt\$1string tidak valid, maka a dikembalikan. BadRequestException 

**Contoh**

```
RETURN ST_GeomFromText('POLYGON((0 0,0 1,1 1,1 0,0 0))')             
POLYGON((0 0,0 1,1 1,1 0,0 0))
```

# ST\$1 AsText
<a name="access-graph-opencypher-22-spatial-functions-st-astext"></a>

ST\$1 AsText mengembalikan representasi teks terkenal (WKT) dari geometri input.

**Sintaksis**

```
ST_AsText(geo)
```

**Argumen**
+ `geo`- Nilai tipe data GEOMETRI, atau ekspresi yang mengevaluasi GEOMETRI.

**Jenis pengembalian**

STRING

Jika geo adalah null, maka null dikembalikan.

Jika parameter input bukan Geometri, maka a BadRequestException dikembalikan.

Jika hasilnya lebih besar dari STRING 64-KB, maka kesalahan dikembalikan.

**Contoh**

```
RETURN ST_AsText(ST_GeomFromText('POLYGON((0 0,0 1,1 1,1 0,0 0))'))             
POLYGON((0 0,0 1,1 1,1 0,0 0))
```

# ST\$1 GeometryType
<a name="access-graph-opencypher-22-spatial-functions-st-geometrytype"></a>

ST\$1 GeometryType mengembalikan jenis geometri sebagai string.

**Sintaksis**

```
ST_GeometryType(geom)
```

**Argumen**
+ `geom`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.

**Jenis pengembalian**

STRING

Jika geom adalah null, maka null dikembalikan.

Jika parameter input bukan Geometri, maka a BadRequestException dikembalikan.

**Contoh**

```
RETURN ST_GeometryType(ST_GeomFromText('LINESTRING(77.29 29.07,77.42 29.26,77.27 29.31,77.29 29.07)'));
ST_LineString
```

# ST\$1sama
<a name="access-graph-opencypher-22-spatial-functions-st-equals"></a>

ST\$1equals mengembalikan true jika proyeksi 2D dari geometri masukan secara topologi sama. Geometri dianggap sama secara topologi jika memiliki himpunan titik yang sama. Dalam geometri yang sama secara topologi, urutan simpul mungkin berbeda sambil mempertahankan kesetaraan ini.

**Sintaksis**

```
ST_Equals(geom1, geom2)
```

**Argumen**
+ `geom1`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.
+ `geom2`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI. Nilai ini dibandingkan dengan geom1 untuk menentukan apakah itu sama dengan geom1.

**Jenis pengembalian**

BOOLEAN

Jika geom1 atau geom2 adalah null, maka null dikembalikan.

Jika geom1 atau geom2 bukan Geometri, maka a dikembalikan. BadRequestException 

**Contoh**

```
RETURN ST_Equals(
    ST_GeomFromText('POLYGON ((0 2,1 1,0 -1,0 2))'), 
    ST_GeomFromText('POLYGON((-1 3,2 1,0 -3,-1 3))'));
false
```

Berikut ini memeriksa apakah kedua garis garis secara geometris sama.

```
RETURN ST_Equals(
    ST_GeomFromText('LINESTRING (1 0, 10 0)'), 
    ST_GeomFromText('LINESTRING(1 0,5 0,10 0)'));
true
```

# ST\$1Berisi
<a name="access-graph-opencypher-22-spatial-functions-st-contains"></a>

ST\$1contains mengembalikan true jika proyeksi 2D dari geometri input pertama berisi proyeksi 2D dari geometri input kedua. Geometri A berisi geometri B jika setiap titik di B adalah titik di A, dan interiornya memiliki persimpangan yang tidak kosong. ST\$1contains (A, B) setara dengan st\$1Within (B, A).

**Sintaksis**

```
ST_Contains(geom1, geom2)
```

**Argumen**
+ `geom1`- Nilai tipe GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.
+ `geom2`- Nilai tipe GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI. Nilai ini dibandingkan dengan geom1 untuk menentukan apakah itu terkandung dalam geom1.

**Jenis pengembalian**

BOOLEAN

Jika geom1 atau geom2 adalah null, maka null dikembalikan.

Jika parameter input bukan Geometri, maka a BadRequestException dikembalikan.

**Contoh**

```
RETURN ST_Contains(
    ST_GeomFromText('POLYGON((0 2,1 1,0 -1,0 2))'), 
    ST_GeomFromText('POLYGON((-1 3,2 1,0 -3,-1 3))'));
false
```

# ST\$1berpotongan
<a name="access-graph-opencypher-22-spatial-functions-st-intersect"></a>

ST\$1Intersects mengembalikan true jika proyeksi 2D dari dua geometri input memiliki setidaknya satu titik yang sama.

**Sintaksis**

```
ST_Intersects(geom1, geom2)
```

**Argumen**
+ `geom1`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.
+ `geom2`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.

**Jenis pengembalian**

BOOLEAN

Jika geom1 atau geom2 adalah null, maka null dikembalikan.

Jika parameter input bukan Geometri, maka a BadRequestException dikembalikan.

**Contoh**

```
RETURN ST_Intersects(
    ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(2 2,2 5,5 5,5 2,2 2))'), 
    ST_GeomFromText('MULTIPOINT((4 4),(6 6))'));
true
```

# ST\$1Jarak
<a name="access-graph-opencypher-22-spatial-functions-st-distance"></a>

Untuk geometri masukan, ST\$1distance mengembalikan jarak Euclidean minimum antara proyeksi 2D dari dua nilai geometri input.

**Sintaksis**

```
ST_Distance(geo1, geo2)
```

**Argumen**
+ `geo1`- Nilai tipe data GEOMETRI, atau ekspresi yang mengevaluasi tipe GEOMETRI.
+ `geo2`- Nilai tipe data GEOMETRI, atau ekspresi yang mengevaluasi GEOMETRI.

**Jenis pengembalian**

PRESISI GANDA dalam satuan yang sama dengan geometri input.

Jika geo1 atau geo2 adalah null, maka null dikembalikan.

Jika parameter input bukan Geometri, maka a BadRequestException dikembalikan.

**Contoh**

```
RETURN ST_Distance(
    ST_GeomFromText('POLYGON((0 2,1 1,0 -1,0 2))'), 
    ST_GeomFromText('POLYGON((-1 -3,-2 -1,0 -3,-1 -3))'));
1.4142135623731
```

# ST\$1 DistanceSpheroid
<a name="access-graph-opencypher-22-spatial-functions-st-distancespheroid"></a>

Mengembalikan jarak minimum dalam meter antara dua lon/lat geometri. Spheroid adalah WGS84 /SRID 4326.

**Sintaksis**

```
ST_DistanceSpheroid(geom1, geom2);
```

**Argumen**
+ `geom1`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.
+ `geom2`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.

**Jenis pengembalian**

FLOAT

Jika geom adalah null, maka null dikembalikan.

**Contoh**

```
RETURN ST_DistanceSpheroid(
    ST_GeomFromText('POINT(-110 42)'),
    ST_GeomFromText('POINT(-118 38)'))
814278.77
```

# ST\$1amplop
<a name="access-graph-opencypher-22-spatial-functions-st-envelope"></a>

ST\$1Envelope mengembalikan kotak batas minimum dari geometri masukan, sebagai berikut:
+ Jika geometri input kosong, geometri yang dikembalikan akan menjadi POINT EMPTY.
+ Jika kotak pembatas minimum dari geometri input merosot ke suatu titik, geometri yang dikembalikan adalah sebuah titik.
+ Jika tidak ada yang sebelumnya benar, fungsi mengembalikan counter-clockwise-oriented poligon yang simpulnya adalah sudut kotak pembatas minimum.

Untuk semua input nonempty, fungsi beroperasi pada proyeksi 2D dari geometri input.

**Sintaksis**

```
ST_Envelope(geom)
```

**Argumen**
+ `geom`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.

**Jenis pengembalian**

GEOMETRY

Jika geom adalah null, maka null dikembalikan.

**Contoh**

```
RETURN ST_Envelope(ST_GeomFromText("POLYGON ((2 1, 4 3, 6 1, 5 5, 3 4, 2 1))"))
POLYGON ((2 1, 6 1, 6 5, 2 5, 2 1))
```

# ST\$1Buffer
<a name="access-graph-opencypher-22-spatial-functions-st-buffer"></a>

ST\$1Buffer mengembalikan geometri 2D yang mewakili semua titik yang jaraknya dari geometri input yang diproyeksikan pada bidang XY-Cartesian kurang dari atau sama dengan jarak input.

**Sintaksis**

```
ST_Buffer(geom, distance, number_of_segments_per_quarter_circle)
```

**Argumen**
+ `geom`- Nilai tipe data GEOMETRI atau ekspresi yang mengevaluasi tipe GEOMETRI.
+ `distance`- Nilai tipe data PRESISI GANDA yang mewakili jarak (atau radius) buffer.
+ `number_of_segments_per_quarter_circle`- Nilai tipe data INTEGER (harus lebih besar atau sama dengan 0). Nilai ini menentukan jumlah titik untuk mendekati seperempat lingkaran di sekitar setiap simpul geometri input. Nilai negatif default ke nol. Defaultnya adalah 8.

**Jenis pengembalian**

GEOMETRY

Fungsi ST\$1Buffer mengembalikan geometri dua dimensi (2D) di bidang XY-Cartesian.

**Contoh**

```
RETURN ST_Buffer(ST_GeomFromText('LINESTRING (1 2,5 2,5 8)'), 2, 4);
POLYGON ((3 4, 3 8, 3.1522409349774265 8.76536686473018,
         3.585786437626905 9.414213562373096, 4.234633135269821 9.847759065022574,
         5 10, 5.765366864730179 9.847759065022574,
         6.414213562373095 9.414213562373096, 6.847759065022574 8.76536686473018,
         7 8, 7 2, 6.847759065022574 1.2346331352698203,
         6.414213562373095 0.5857864376269051, 5.765366864730179 0.1522409349774265,
         5 0, 1 0, 0.2346331352698193 0.152240934977427,
         -0.4142135623730954 0.5857864376269051,
         -0.8477590650225737 1.2346331352698208, -1 2.0000000000000004,
         -0.8477590650225735 2.7653668647301797,
         -0.4142135623730949 3.414213562373095,
         0.2346331352698206 3.8477590650225735, 1 4, 3 4))
```

Berikut ini mengembalikan buffer dari geometri titik input yang mendekati lingkaran. Karena perintah menentukan 3 sebagai jumlah segmen per seperempat lingkaran, fungsi menggunakan tiga segmen untuk memperkirakan lingkaran seperempat.

```
RETURN ST_Buffer(ST_GeomFromText('POINT (1 1)'), 1.0, 8));
POLYGON ((2 1, 1.9807852804032304 0.8049096779838718,
     1.9238795325112867 0.6173165676349102, 1.8314696123025453 0.4444297669803978,
     1.7071067811865475 0.2928932188134525, 1.5555702330196022 0.1685303876974548,
     1.3826834323650898 0.0761204674887133, 1.1950903220161284 0.0192147195967696,
     1 0, 0.8049096779838718 0.0192147195967696, 0.6173165676349103 0.0761204674887133,
    0.444429766980398 0.1685303876974545, 0.2928932188134525 0.2928932188134524,
     0.1685303876974546 0.4444297669803978, 0.0761204674887133 0.6173165676349102,
     0.0192147195967696 0.8049096779838714, 0 0.9999999999999999,
     0.0192147195967696 1.1950903220161284, 0.0761204674887132 1.3826834323650896,
     0.1685303876974545 1.555570233019602, 0.2928932188134523 1.7071067811865475,
     0.4444297669803978 1.8314696123025453, 0.6173165676349097 1.9238795325112865,
     0.8049096779838714 1.9807852804032304, 0.9999999999999998 2,
     1.1950903220161284 1.9807852804032304, 1.38268343236509 1.9238795325112865,
     1.5555702330196017 1.8314696123025453, 1.7071067811865475 1.7071067811865477,
     1.8314696123025453 1.5555702330196022, 1.9238795325112865 1.3826834323650905,
     1.9807852804032304 1.1950903220161286, 2 1))
```

# Mengakses grafik Neptune dengan SPARQL
<a name="access-graph-sparql"></a>

SPARQL adalah bahasa kueri untuk Resource Description Framework (RDF), yang merupakan format data grafik yang dirancang untuk web. Amazon Neptune kompatibel dengan SPARQL 1.1. Ini berarti bahwa Anda dapat terhubung ke instans DB Neptune dan mengajukan kueri grafik menggunakan bahasa kueri yang dijelaskan dalam spesifikasi [Bahasa Kueri SPARQL 1.1](https://www.w3.org/TR/sparql11-query/).

 Sebuah kueri di SPARQL terdiri dari klausa `SELECT` untuk menentukan variabel yang akan dikembalikan dan klausa `WHERE` untuk menentukan data yang mana yang akan dicocokkan dalam grafik. Jika Anda tidak terbiasa dengan kueri SPARQL, lihat [Menulis Kueri Sederhana](https://www.w3.org/TR/sparql11-query/#WritingSimpleQueries) dalam [Bahasa Kueri SPARQL 1.1](https://www.w3.org/TR/sparql11-query/).

**penting**  
Untuk memuat data, `SPARQL UPDATE INSERT` dapat bekerja dengan baik untuk set data kecil, tetapi jika Anda perlu memuat sejumlah besar data dari sebuah file, lihat [Menggunakan pemuat massal Amazon Neptunus untuk menelan data](bulk-load.md).

Untuk informasi selengkapnya tentang spesifikasi implementasi SPARQL Neptune, lihat [Kepatuhan standar SPARQL](feature-sparql-compliance.md).

Sebelum Anda mulai, Anda harus memiliki yang berikut:
+ Instans DB Neptune. Untuk informasi tentang membuat instans DB Neptune, lihat [Membuat cluster Amazon Neptunus](get-started-create-cluster.md).
+ Instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans DB Neptune Anda.

**Topics**
+ [Menggunakan konsol RDF4 J untuk terhubung ke instance DB Neptunus](access-graph-sparql-rdf4j-console.md)
+ [Menggunakan RDF4 J Workbench untuk terhubung ke instans DB Neptunus](access-graph-sparql-rdf4j-workbench.md)
+ [Gunakan Java untuk terhubung ke instans DB Neptune](access-graph-sparql-java.md)
+ [API HTTP SPARQL](sparql-api-reference.md)
+ [Petunjuk kueri SPARQL](sparql-query-hints.md)
+ [Perilaku DESKRIPSI SPARQL sehubungan dengan grafik default](sparql-default-describe.md)
+ [API status kueri SPARQL](sparql-api-status.md)
+ [Pembatalan kueri SPARQL](sparql-api-status-cancel.md)
+ [Menggunakan Protokol HTTP (GSP) SPARQL 1.1 Graph Store di Amazon Neptunus](sparql-graph-store-protocol.md)
+ [Menganalisis eksekusi kueri Neptune menggunakan `explain` SPARQL](sparql-explain.md)
+ [Kueri gabungan SPARQL di Neptune menggunakan ekstensi `SERVICE`](sparql-service.md)

# Menggunakan konsol RDF4 J untuk terhubung ke instance DB Neptunus
<a name="access-graph-sparql-rdf4j-console"></a>



Konsol RDF4 J memungkinkan Anda bereksperimen dengan grafik dan kueri Resource Description Framework (RDF) di lingkungan REPL (loop). read-eval-print 

Anda dapat menambahkan database grafik jarak jauh sebagai repositori dan menanyakannya dari Konsol RDF4 J. Bagian ini memandu Anda melalui konfigurasi Konsol RDF4 J untuk terhubung dari jarak jauh ke instans DB Neptunus.

**Untuk terhubung ke Neptunus menggunakan Konsol J RDF4**

1. Unduh RDF4 J SDK dari [halaman Unduh](http://rdf4j.org/download/) di situs web RDF4 J.

1. Buka zip file zip RDF4 J SDK.

1. Di terminal, arahkan ke direktori RDF4 J SDK, lalu masukkan perintah berikut untuk menjalankan Konsol RDF4 J:

   ```
   bin/console.sh
   ```

   Anda akan melihat output yang serupa dengan yang berikut:

   ```
   14:11:51.126 [main] DEBUG o.e.r.c.platform.PlatformFactory - os.name = linux
   14:11:51.130 [main] DEBUG o.e.r.c.platform.PlatformFactory - Detected Posix platform
   Connected to default data directory
   RDF4J Console 3.6.1
   
   3.6.1
   Type 'help' for help.
   >
   ```

   Anda sekarang berada di prompt `>`. Ini adalah prompt umum untuk Konsol RDF4 J. Anda menggunakan prompt ini untuk menyiapkan repositori dan operasi lainnya. Repositori memiliki prompt sendiri untuk menjalankan kueri.

1. Di prompt `>`, masukkan hal berikut ini untuk membuat repositori SPARQL untuk instans DB Neptune Anda:

    

   ```
   create sparql
   ```

1. Konsol RDF4 J meminta Anda untuk nilai untuk variabel yang diperlukan untuk terhubung ke titik akhir SPARQL.

   ```
   Please specify values for the following variables:
   ```

   Tentukan nilai-nilai berikut ini:    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/neptune/latest/userguide/access-graph-sparql-rdf4j-console.html)

   Untuk informasi tentang menemukan alamat instans DB Neptune Anda, lihat bagian [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md).

   Jika operasi berhasil, Anda akan melihat pesan berikut:

    

   ```
   Repository created
   ```

1. Di prompt `>`, masukkan hal berikut untuk menyambung ke instans DB Neptune.

   ```
   open neptune
   ```

   Jika operasi berhasil, Anda akan melihat pesan berikut:

    

   ```
   Opened repository 'neptune'
   ```

   Anda sekarang berada di prompt `neptune>`. Pada prompt ini, Anda dapat menjalankan kueri terhadap grafil Neptune.

    
**catatan**  
Sekarang setelah Anda menambahkan repositori, saat berikutnya Anda menjalankan `bin/console.sh`, Anda dapat segera menjalankan perintah `open neptune` untuk menyambung ke instans DB Neptune.

1. Pada `neptune>` prompt, masukkan berikut ini untuk menjalankan query SPARQL yang mengembalikan hingga 10 dari triple (subject-predicate-object) dalam grafik dengan menggunakan `?s ?p ?o` kueri dengan batas 10. Untuk mengajukan kueri untuk sesuatu yang lain, gantikan teks setelah perintah `sparql` dengan kueri SPARQL lain.

   ```
   sparql select ?s ?p ?o where {?s ?p ?o} limit 10
   ```

# Menggunakan RDF4 J Workbench untuk terhubung ke instans DB Neptunus
<a name="access-graph-sparql-rdf4j-workbench"></a>

Bagian ini memandu Anda melalui koneksi ke instans Amazon Neptunus DB RDF4 menggunakan J RDF4 Workbench dan J Server. RDF4J Server diperlukan karena bertindak sebagai proxy antara titik akhir Neptunus SPARQL HTTP REST dan J Workbench. RDF4 

RDF4J Workbench menyediakan antarmuka yang mudah untuk bereksperimen dengan grafik, termasuk memuat file lokal. Untuk informasi, lihat [bagian Tambah](https://rdf4j.org/documentation/tools/server-workbench/#add) dalam dokumentasi RDF4 J.

**Prasyarat**  
Sebelum memulai, lakukan hal berikut:
+ Pasang Java 1.8 atau yang lebih baru.
+ Instal RDF4 J Server dan RDF4 J Workbench. Untuk selengkapnya, lihat [Menginstal RDF4 J Server dan RDF4 J Workbench](https://rdf4j.org/documentation/tools/server-workbench/#installing-rdf4j-server-and-rdf4j-workbench).

**Untuk menggunakan RDF4 J Workbench untuk terhubung ke Neptunus**

1. Di browser web, navigasikan ke URL tempat aplikasi web RDF4 J Workbench digunakan. Misalnya, jika Anda menggunakan Apache Tomcat, URL-nya adalah: [https: //:8080/rdf4j-workbench/](http://localhost:8080/rdf4j-workbench/). *ec2\$1hostname*

1. Jika Anda diminta untuk **Connect to RDF4 J Server**, verifikasi bahwa **RDF4J Server** diinstal, berjalan, dan bahwa URL server sudah benar. Kemudian, lanjutkan ke langkah berikutnya.

1. Di panel sebelah kiri, pilih **Repositori baru**.

   Dalam **Repositori baru**:
   + Di daftar menurun **Jenis**, pilih **Proksi titik akhir SPARQL**.
   + Untuk **ID**, ketikkan **Neptune**.
   + Untuk **Judul**, ketikkan **Instans DB Neptune**.

   Pilih **Berikutnya**.

1. Dalam **Repositori baru**:
   + Untuk **URL titik akhir kueri SPARQL**, ketikkan `https://your-neptune-endpoint:port/sparql`.
   + Untuk **URL titik akhir pembaruan SPARQL**, ketikkan `https://your-neptune-endpoint:port/sparql`.

   Untuk informasi tentang menemukan alamat instans DB Neptune Anda, lihat bagian [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md). 

   Pilih **Buat**.

1. Repositori **neptune** kini muncul dalam daftar repositori. Mungkin perlu beberapa menit sebelum Anda dapat menggunakan repositori baru.

1. Di kolom **Id** pada tabel, pilih tautan **neptune**.

1. Di panel sebelah kiri, pilih **Kueri**. 

    
**catatan**  
Jika item menu di bawah **Jelajahi** dinonaktifkan, Anda mungkin perlu menyambung kembali ke Server RDF4 J dan memilih repositori **neptune** lagi.  
Anda dapat melakukan hal ini menggunakan tautan **[perubahan]** di sudut kanan atas.

1. Di bidang kueri, ketik kueri SPARQL berikut, lalu pilih **Eksekusi**.

    

   ```
   select ?s ?p ?o where {?s ?p ?o} limit 10
   ```

    

Contoh sebelumnya mengembalikan hingga 10 dari triple (subject-predicate-object) dalam grafik dengan menggunakan `?s ?p ?o` query dengan batas 10. 

# Gunakan Java untuk terhubung ke instans DB Neptune
<a name="access-graph-sparql-java"></a>

Bagian ini memandu Anda melalui proses berjalannya sampel Java lengkap yang menyambungkan ke instans DB Amazon Neptune dan melakukan kueri SPARQL.

Ikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans Neptune DB Anda.

**Untuk menyambung ke Neptune menggunakan Java**

1. Install Apache Maven pada instans EC2 Anda. Jika menggunakan Amazon Linux 2023 (lebih disukai), gunakan:

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

   Jika menggunakan Amazon Linux 2, unduh biner terbaru dari [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. Contoh ini diuji hanya dengan Java 8. Masukkan hal berikut ini untuk menginstal Java 8 pada instans EC2 Anda:

   ```
   sudo yum install java-1.8.0-devel
   ```

1. Masukkan hal berikut untuk mengatur Java 8 sebagai runtime default pada instans EC2 Anda:

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

   Saat diminta, masukkan nomor untuk Java 8.

1. Masukkan hal berikut untuk mengatur Java 8 sebagai compiler default pada instans EC2 Anda: 

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

   Saat diminta, masukkan nomor untuk Java 8.

1. Di direktori baru, buat file `pom.xml`, lalu buka file tersebut dalam editor teks.

1. Salin hal berikut ke file `pom.xml` dan simpan (Anda biasanya dapat menyesuaikan nomor versi ke versi stabil terbaru):

   ```
   <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">
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.amazonaws</groupId>
     <artifactId>RDFExample</artifactId>
     <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>RDFExample</name>
     <url>https://maven.apache.org</url>
     <dependencies>
       <dependency>
         <groupId>org.eclipse.rdf4j</groupId>
         <artifactId>rdf4j-runtime</artifactId>
         <version>3.6</version>
       </dependency>
     </dependencies>
     <build>
       <plugins>
         <plugin>
             <groupId>org.codehaus.mojo</groupId>
             <artifactId>exec-maven-plugin</artifactId>
             <version>1.2.1</version>
             <configuration>
               <mainClass>com.amazonaws.App</mainClass>
             </configuration>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <configuration>
             <source>1.8</source>
             <target>1.8</target>
           </configuration>
         </plugin>
       </plugins>
     </build>
   </project>
   ```
**catatan**  
Jika Anda memodifikasi proyek Maven yang ada, dependensi yang diperlukan disorot dalam kode sebelumnya.

1. Untuk membuat subdirektori untuk kode sumber contoh (`src/main/java/com/amazonaws/`), masukkan hal berikut ke baris perintah:

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

1. Di direktori `src/main/java/com/amazonaws/`, buat file bernama `App.java`, lalu buka file tersebut dalam editor teks.

1. Salin hal berikut ke dalam file `App.java`. Ganti *your-neptune-endpoint* dengan alamat instans DB Neptunus Anda.
**catatan**  
Untuk informasi tentang menemukan nama host instans DB Neptune Anda, lihat [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md). 

   ```
   package com.amazonaws;
   
   import org.eclipse.rdf4j.repository.Repository;
   import org.eclipse.rdf4j.repository.http.HTTPRepository;
   import org.eclipse.rdf4j.repository.sparql.SPARQLRepository;
   
   import java.util.List;
   import org.eclipse.rdf4j.RDF4JException;
   import org.eclipse.rdf4j.repository.RepositoryConnection;
   import org.eclipse.rdf4j.query.TupleQuery;
   import org.eclipse.rdf4j.query.TupleQueryResult;
   import org.eclipse.rdf4j.query.BindingSet;
   import org.eclipse.rdf4j.query.QueryLanguage;
   import org.eclipse.rdf4j.model.Value;
   
   public class App
   {
       public static void main( String[] args )
       {
           String sparqlEndpoint = "https://your-neptune-endpoint:port/sparql";
           Repository repo = new SPARQLRepository(sparqlEndpoint);
           repo.initialize();
   
           try (RepositoryConnection conn = repo.getConnection()) {
              String queryString = "SELECT ?s ?p ?o WHERE { ?s ?p ?o } limit 10";
   
              TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
   
              try (TupleQueryResult result = tupleQuery.evaluate()) {
                 while (result.hasNext()) {  // iterate over the result
                      BindingSet bindingSet = result.next();
   
                      Value s = bindingSet.getValue("s");
                      Value p = bindingSet.getValue("p");
                      Value o = bindingSet.getValue("o");
   
                      System.out.print(s);
                      System.out.print("\t");
                      System.out.print(p);
                      System.out.print("\t");
                      System.out.println(o);
                 }
              }
           }
       }
   }
   ```

1. Gunakan perintah Maven berikut untuk mengonpilasi dan menjalankan sampel:

   ```
   mvn compile exec:java
   ```

Contoh sebelumnya mengembalikan hingga 10 dari triple (subject-predicate-object) dalam grafik dengan menggunakan `?s ?p ?o` query dengan batas 10. Untuk mengajukan kueri untuk sesuatu yang lain, gantikan kueri tersebut dengan kueri SPARQL lain.

Iterasi hasil dalam contoh mencetak nilai masing-masing variabel yang dkembalikan. Objek `Value` dikonversi menjadi `String` lalu dicetak. Jika Anda mengubah bagian `SELECT` dari kueri, Anda harus memodifikasi kodenya.

# API HTTP SPARQL
<a name="sparql-api-reference"></a>

Permintaan HTTP SPARQL diterima di titik akhir berikut: `https://your-neptune-endpoint:port/sparql`

Untuk informasi selengkapnya tentang menyambung ke Amazon Neptune dengan SPARQL, lihat [Mengakses grafik Neptune dengan SPARQL](access-graph-sparql.md).

Untuk informasi selengkapnya tentang protokol SPARQL dan bahasa kueri, lihat [Protokol SPARQL 1.1](https://www.w3.org/TR/sparql11-protocol/#protocol) dan spesifikasi [Bahasa kueri SPARQL 1.1](https://www.w3.org/TR/sparql11-query/).

Topik berikut memberikan informasi tentang format serialisasi SPARQL RDF dan cara menggunakan API HTTP SPARQL dengan Neptune.

**Contents**
+ [Menggunakan titik akhir HTTP REST untuk menyambung ke instans DB Neptune](access-graph-sparql-http-rest.md)
+ [Header di belakang HTTP opsional untuk respons SPARQL multi-bagian](access-graph-sparql-http-trailing-headers.md)
+ [Jenis media RDF yang digunakan oleh SPARQL di Neptune](sparql-media-type-support.md)
  + [Format serialisasi RDF digunakan oleh SPARQL Neptune](sparql-media-type-support.md#sparql-serialization-formats)
  + [Format serialisasi hasil SPARQL yang digunakan oleh Neptune SPARQL](sparql-media-type-support.md#sparql-serialization-formats-neptune-output)
  + [Jenis Media yang dapat digunakan Neptune untuk mengimpor data RDF](sparql-media-type-support.md#sparql-serialization-formats-input)
  + [Jenis media yang dapat digunakan Neptune untuk mengekspor hasil kueri](sparql-media-type-support.md#sparql-serialization-formats-output)
+ [Menggunakan SPARQL UPDATE LOAD untuk mengimpor data ke Neptune](sparql-api-reference-update-load.md)
+ [Menggunakan SPARQL UPDATE UNLOAD untuk menghapus data dari Neptune](sparql-api-reference-unload.md)

# Menggunakan titik akhir HTTP REST untuk menyambung ke instans DB Neptune
<a name="access-graph-sparql-http-rest"></a>

**catatan**  
Neptunus saat ini tidak mendukung HTTP/2 untuk permintaan REST API. Klien harus menggunakan HTTP/1.1 saat menghubungkan ke titik akhir.

Petunjuk berikut memandu Anda menyambungkan ke titik akhir SPARQL menggunakan perintah **curl**, menyambungkan melalui HTTPS, dan menggunakan sintaks HTTP. Ikuti petunjuk ini dari instans Amazon EC2 di virtual private cloud (VPC) yang sama seperti instans Neptune DB Anda.

Titik akhir HTTP untuk kueri SPARQL ke instans DB Neptune adalah: `https://your-neptune-endpoint:port/sparql`.

**catatan**  
Untuk informasi tentang menemukan nama host instans DB Neptune Anda, lihat [Menghubungkan ke Titik Akhir Amazon Neptune.](feature-overview-endpoints.md).

Amazon Neptune menyediakan titik akhir HTTP untuk kueri SPARQL. Antarmuka REST kompatibel dengan SPARQL versi 1.1.

**KUERI Menggunakan HTTP POST**  
Contoh berikut menggunakan **curl** untuk mengirimkan **`QUERY`** SPARQL melalui **POST** HTTP.

```
curl -X POST --data-binary 'query=select ?s ?p ?o where {?s ?p ?o} limit 10' https://your-neptune-endpoint:port/sparql
```

Contoh sebelumnya mengembalikan hingga 10 dari triple (subject-predicate-object) dalam grafik dengan menggunakan `?s ?p ?o` query dengan batas 10. Untuk mengajukan kueri untuk sesuatu yang lain, gantikan dengan kueri SPARQL lain.

**catatan**  
Jenis media MIME default respon adalah `application/sparql-results+json` untuk kueri `SELECT` dan `ASK`.  
Jenis MIME default respon adalah `application/n-quads` untuk kueri `CONSTRUCT` dan `DESCRIBE`.  
Untuk daftar jenis media yang digunakan oleh Neptune untuk serialisasi, lihat [Format serialisasi RDF digunakan oleh SPARQL Neptune](sparql-media-type-support.md#sparql-serialization-formats).

**PEMBARUAN Menggunakan HTTP POST**  
Contoh berikut menggunakan **curl** untuk mengirimkan **`UPDATE`** SPARQL melalui **POST** HTTP.

```
curl -X POST --data-binary 'update=INSERT DATA { <https://test.com/s> <https://test.com/p> <https://test.com/o> . }' https://your-neptune-endpoint:port/sparql
```

Contoh sebelumnya menyisipkan tripel berikut ke dalam grafik default SPARQL: `<https://test.com/s> <https://test.com/p> <https://test.com/o>`

# Header di belakang HTTP opsional untuk respons SPARQL multi-bagian
<a name="access-graph-sparql-http-trailing-headers"></a>

Respon HTTP untuk kueri dan pembaruan SPARQL sering dikembalikan dalam lebih dari satu bagian atau potongan. Sulit untuk mendiagnosa kegagalan yang terjadi setelah kueri atau pembaruan mulai mengirimkan potongan ini, terutama karena yang pertama tiba dengan kode status HTTP `200`.

Kecuali Anda secara eksplisit meminta header trailing, Neptune hanya melaporkan kegagalan tersebut dengan menambahkan pesan kesalahan ke badan pesan, yang biasanya rusak.

Untuk memudahkan deteksi dan diagnosis masalah semacam ini, Anda dapat menyertakan header trailer transfer-encoding (TE) (`te: trailers`) dalam permintaan Anda (lihat, misalnya, [halaman MDN tentang header permintaan TE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/TE)). Melakukan hal ini akan menyebabkan Neptune menyertakan dua bidang header baru dalam header trailing dari potongan respons:
+ `X-Neptune-Status`  –   berisi kode respons diikuti dengan nama pendek. Misalnya, dalam kasus keberhasilan, header trailing akan berupa: `X-Neptune-Status: 200 OK`. Dalam kasus kegagalan, kode respons akan berupa [kode kesalahan mesin Neptune](errors-engine-codes.md), seperti `X-Neptune-Status: 500 TimeLimitExceededException`.
+ `X-Neptune-Detail`  –   kosong untuk permintaan yang berhasil. Dalam kasus kesalahan, ia berisi pesan kesalahan JSON. Karena hanya karakter ASCII yang diperbolehkan dalam nilai header HTTP, string JSON di-enkode dengan URL. Pesan kesalahan juga masih ditambahkan ke badan pesan respons.

# Jenis media RDF yang digunakan oleh SPARQL di Neptune
<a name="sparql-media-type-support"></a>

Data Resource Description Framework (RDF) dapat diserialkan dalam berbagai cara, yang sebagian besar dapat dikonsumsi atau dioutput oleh SPARQL:

## Format serialisasi RDF digunakan oleh SPARQL Neptune
<a name="sparql-serialization-formats"></a>
+ **RDF/XML**  –   serialisasi XML dari RDF, didefinisikan dalam [Sintaks XML RDF 1.1](https://www.w3.org/TR/rdf-syntax-grammar/). Jenis media: `application/rdf+xml`. Ekstensi file umum: `.rdf`.
+ **N–Tripel**  –   Format teks biasa berbasis baris untuk encoding grafik RDF, didefinisikan dalam [N-Tripel RDF 1.1](https://www.w3.org/TR/n-triples/). Jenis media: `application/n-triples`, `text/turtle`, atau `text/plain`. Ekstensi file umum: `.nt`.
+ **N–Quad**  –   Format teks biasa berbasis baris untuk encoding grafik RDF, didefinisikan dalam [N-Quad RDF 1.1](https://www.w3.org/TR/n-quads/). Ini adalah perpanjangan dari N-Tripel. Jenis media: `application/n-quads`, atau `text/x-nquads` saat dikodekan dengan US-ASCII 7-bit. Ekstensi file umum: `.nq`.
+ **Turtle**  –   Sebuah sintaks tekstual untuk RDF yang didefinisikan dalam [Turtle RDF 1.1](https://www.w3.org/TR/turtle/) yang memungkinkan grafik RDF untuk sepenuhnya ditulis dalam bentuk teks yang ringkas dan alami, dengan singkatan untuk pola penggunaan dan tipe data umum. Turtle menyediakan tingkat kompatibilitas dengan format N-Tripel serta sintaks pola tripel SPARQL. Jenis media: `text/turtle`Ekstensi file umum: `.ttl`.
+ **Turtle**  –   Sebuah sintaks tekstual untuk RDF yang didefinisikan dalam [TriG RDF 1.1](https://www.w3.org/TR/trig/) yang memungkinkan grafik RDF untuk sepenuhnya ditulis dalam bentuk teks yang ringkas dan alami, dengan singkatan untuk pola penggunaan dan tipe data umum. TriG adalah perpanjangan dari format Turtle. Jenis media: `application/trig`. Ekstensi file umum: `.trig`.
+ **N3 (Notation3)**  –   Sebuah bahasa pernyataan dan logika yang didefinisikan dalam [Notation3 (N3): Sebuah sintaks RDF yang dapat dibaca](https://www.w3.org/TeamSubmission/n3/). N3 memperluas model data RDF dengan menambahkan formula-formula (benar-benar berbentuk grafik), variabel, implikasi logis, dan predikat fungsional, dan menyediakan alternatif sintaks tekstual untuk RDF/XML. Jenis media: `text/n3`. Ekstensi file umum: `.n3`.
+ **JSON-LD**  –   Sebuah serialisasi data dan format pesan yang didefinisikan dalam [JSON-LD 1.0](https://www.w3.org/TR/json-ld/). Jenis media: `application/ld+json`. Ekstensi file umum: `.jsonld`.
+ **TriX**  –   Sebuah serialisasi RDF dalam XML, didefinisikan dalam [TriX: RDF Triple dalam XML](https://www.hpl.hp.com/techreports/2004/HPL-2004-56.html). Jenis media: `application/trix`. Ekstensi file umum: `.trix`.
+ **Hasil JSON SPARQL**  –   Sebuah serialisasi RDF menggunakan [Format JSON Hasil Kueri SPARQL 1.1](https://www.w3.org/TR/sparql11-results-json). Jenis media: `application/sparql-results+json`. Ekstensi file umum: `.srj`.
+ **RDF4J Binary Format — Format** biner untuk pengkodean data RDF, didokumentasikan dalam [RDF4J Binary](https://rdf4j.org/documentation/reference/rdf4j-binary) RDF Format. Jenis media: `application/x-binary-rdf`.

## Format serialisasi hasil SPARQL yang digunakan oleh Neptune SPARQL
<a name="sparql-serialization-formats-neptune-output"></a>
+ **Hasil XML SPARQL**  –   Format XML untuk format hasil variabel binding dan boolean yang disediakan oleh bahasa kueri SPARQL, didefinisikan dalam[Format XML Hasil Kueri SPARQL (Edisi Kedua)](https://www.w3.org/TR/rdf-sparql-XMLres/). Jenis media: `application/sparql-results+xml`. Ekstensi file umum: `.srx`.
+ **Hasil CSV dan TSV SPARQL**  –   Penggunaan nilai dipisahkan koma dan nilai dipisahkan tab untuk mengekspresikan hasil kueri SPARQL dari kueri `SELECT`, didefinisikan dalam [Format CSV dan TSV Hasil Kueri SPARQL 1.1](https://www.w3.org/TR/sparql11-results-csv-tsv/). Jenis media: `text/csv` untuk nilai yang dipisahkan koma, dan `text/tab-separated-values` untuk nilai yang dipisahkan tab. Ekstensi file umum: `.csv` untuk nilai yang dipisahkan koma, dan `.tsv` untuk nilai yang dipisahkan tab.
+ **Tabel Hasil Biner**  –   Format biner untuk mengkodekan output kueri SPARQL. Jenis media: `application/x-binary-rdf-results-table`.
+ **Hasil JSON SPARQL**  –   Sebuah serialisasi RDF menggunakan [Format JSON Hasil Kueri SPARQL 1.1](https://www.w3.org/TR/sparql11-results-json/). Jenis media: `application/sparql-results+json`.

## Jenis Media yang dapat digunakan Neptune untuk mengimpor data RDF
<a name="sparql-serialization-formats-input"></a>

**Jenis media yang didukung oleh [bulk-loader Neptune](bulk-load.md)**
+ [N-Tiga](https://www.w3.org/TR/n-triples/)
+ [N-Quads](https://www.w3.org/TR/n-quads/)
+ [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/)
+ [Kura-kura](https://www.w3.org/TR/turtle/)

**Jenis media yang dapat diimpor SPARQL UPDATE LOAD**
+ [N-Tiga](https://www.w3.org/TR/n-triples/)
+ [N-Quads](https://www.w3.org/TR/n-quads/)
+ [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/)
+ [Kura-kura](https://www.w3.org/TR/turtle/)
+ [TriG](https://www.w3.org/TR/trig/)
+ [N3](https://www.w3.org/TeamSubmission/n3/)
+ [JSON-LD](https://www.w3.org/TR/json-ld/)

## Jenis media yang dapat digunakan Neptune untuk mengekspor hasil kueri
<a name="sparql-serialization-formats-output"></a>

Untuk menentukan format output untuk respons kueri SPARQL, kirim header `"Accept: media-type"` dengan permintaan kueri. Contoh:

```
curl -H "Accept: application/nquads" ...
```

**Jenis media RDF yang dapat dioutput SPARQL SELECT dari Neptune**
+ [Hasil JSON SPARQL](https://www.w3.org/TR/sparql11-results-json) (Ini adalah pengaturan default)
+ [Hasil XMLSPARQL](https://www.w3.org/TR/rdf-sparql-XMLres/)
+ **Tabel Hasil Biner** (jenis media: `application/x-binary-rdf-results-table`)
+ [Nilai yang Dipisahkan Koma (CSV)](https://www.w3.org/TR/sparql11-results-csv-tsv/)
+ [Nilai yang Dipisahkan Tab (TSV)](https://www.w3.org/TR/sparql11-results-csv-tsv/)

**Jenis media RDF yang dapat dioutput SPARQL ASK dari Neptune**
+ [Hasil JSON SPARQL](https://www.w3.org/TR/sparql11-results-json) (Ini adalah pengaturan default)
+ [Hasil XMLSPARQL](https://www.w3.org/TR/rdf-sparql-XMLres/)
+ **Boolean** (jenis media: `text/boolean`, yang berarti “benar” atau “salah”)

**Jenis media RDF yang dapat dioutput SPARQL CONSTRUCT dari Neptune**
+ [N-Quad](https://www.w3.org/TR/n-quads/) (Ini adalah pengaturan default)
+ [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/)
+ [JSON-LD](https://www.w3.org/TR/json-ld/)
+ [N-Tiga Kali Lipat](https://www.w3.org/TR/n-triples/)
+ [Kura-kura](https://www.w3.org/TR/turtle/)
+ [N3](https://www.w3.org/TeamSubmission/n3/)
+ [TriX](https://www.hpl.hp.com/techreports/2004/HPL-2004-56.html)
+ [TriG](https://www.w3.org/TR/trig/)
+ [Hasil SPARQL JSON](https://www.w3.org/TR/sparql11-results-json)
+ [RDF4Format RDF Biner J](https://rdf4j.org/documentation/reference/rdf4j-binary)

**Jenis media RDF yang dapat dioutput SPARQL DESCRIBE dari Neptune**
+ [N-Quad](https://www.w3.org/TR/n-quads/) (Ini adalah pengaturan default)
+ [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/)
+ [JSON-LD](https://www.w3.org/TR/json-ld/)
+ [N-Tiga Kali Lipat](https://www.w3.org/TR/n-triples/)
+ [Kura-kura](https://www.w3.org/TR/turtle/)
+ [N3](https://www.w3.org/TeamSubmission/n3/)
+ [TriX](https://www.hpl.hp.com/techreports/2004/HPL-2004-56.html)
+ [TriG](https://www.w3.org/TR/trig/)
+ [Hasil SPARQL JSON](https://www.w3.org/TR/sparql11-results-json)
+ [RDF4Format RDF Biner J](https://rdf4j.org/documentation/reference/rdf4j-binary)

# Menggunakan SPARQL UPDATE LOAD untuk mengimpor data ke Neptune
<a name="sparql-api-reference-update-load"></a>

Sintaks perintah SPARQL UPDATE LOAD ditentukan dalam [Rekomendasi pembaruan SPARQL 1.1](https://www.w3.org/TR/sparql11-update/#load):

```
LOAD SILENT (URL of data to be loaded) INTO GRAPH (named graph into which to load the data)
```
+ **`SILENT`**   –   (*Opsional*) Menyebabkan operasi mengembalikan sukses bahkan jika ada kesalahan selama pemrosesan.

  Hal ini dapat berguna ketika transaksi tunggal berisi beberapa pernyataan seperti `"LOAD ...; LOAD ...; UNLOAD ...; LOAD ...;"` dan Anda ingin transaksinya selesai bahkan jika beberapa data jarak jauh tidak dapat diproses.
+ *URL of data to be loaded*- (*Wajib*) Menentukan file data jarak jauh yang berisi data yang akan dimuat ke dalam grafik.

  File jarak jauh harus memiliki salah satu ekstensi berikut:
  + `.nt`untuk NTriples.
  + `.nq`untuk NQuads.
  + `.trig` untuk Trig.
  + `.rdf` untuk RDF/XML.
  + `.ttl` untuk Turtle.
  + `.n3` untuk N3.
  + `.jsonld` untuk JSON-LD.
+ **`INTO GRAPH`***(named graph into which to load the data)*— (*Opsional*) Menentukan grafik ke mana data harus dimuat.

  Neptune mengasosiasikan setiap tripel dengan grafik bernama. Anda dapat menentukan grafik bernama default menggunakan URI grafik bernama fallback, `http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph`, seperti ini:

  ```
  INTO GRAPH <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph>
  ```

**catatan**  
Bila Anda perlu memuat banyak data, sebaiknya gunakan pemuat massal Neptune alih-alih UPDATE LOAD. Untuk informasi lebih lanjut tentang pemuat massal, lihat [Menggunakan pemuat massal Amazon Neptunus untuk menelan data](bulk-load.md).

Anda dapat menggunakan `SPARQL UPDATE LOAD` untuk memuat data langsung dari Amazon S3, atau dari file yang diperoleh dari server web yang di-host sendiri. Sumber daya yang akan dimuat harus berada di wilayah yang sama seperti server Neptune, dan titik akhir untuk sumber daya harus diizinkan dalam VPC. Untuk informasi tentang cara membuat titik akhir Amazon S3, lihat [Membuat VPC Endpoint Amazon S3](bulk-load-data.md#bulk-load-prereqs-s3).

Semua `SPARQL UPDATE LOAD` URIs harus dimulai dengan`https://`. Ini termasuk Amazon S3 URLs.

Berbeda dengan loader massal Neptune, panggilan ke `SPARQL UPDATE LOAD` sepenuhnya transaksional.

**Memuat file langsung dari Amazon S3 ke Neptune menggunakan SPARQL UPDATE LOAD**

Karena Neptune tidak mengizinkan Anda untuk melewatkan IAM role ke Amazon S3 ketika menggunakan SPARQL UPDATE LOAD, baik bucket Amazon S3 yang bersangkutan harus publik atau Anda harus menggunakan [URL Amazon S3 pre-signed](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html) dalam kueri LOAD.

Untuk menghasilkan URL yang telah ditandatangani sebelumnya untuk file Amazon S3, Anda dapat menggunakan AWS CLI perintah seperti ini:

```
aws s3 presign --expires-in (number of seconds) s3://(bucket name)/(path to file of data to load)
```

Kemudian Anda dapat menggunakan URL pre-signed yang dihasilkan di dalam perintah `LOAD` Anda:

```
curl https://(a Neptune endpoint URL):8182/sparql \
  --data-urlencode 'update=load (pre-signed URL of the remote Amazon S3 file of data to be loaded) \
                           into graph (named graph)'
```

Untuk informasi lebih lanjut, lihat [Melakukan Autentikasi Permintaan: Menggunakan Parameter Kueri](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html). [Dokumentasi Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html) menunjukkan cara menggunakan script Python untuk menghasilkan URL pre-signed.

Selain itu, jenis konten file yang akan dimuatkan mesti ditetapkan dengan benar.

1. Atur jenis konten file ketika Anda meng-upload mereka ke Amazon S3 dengan menggunakan parameter `-metadata`, seperti ini:

   ```
   aws s3 cp test.nt s3://bucket-name/my-plain-text-input/test.nt --metadata Content-Type=text/plain
   aws s3 cp test.rdf s3://bucket-name/my-rdf-input/test.rdf --metadata Content-Type=application/rdf+xml
   ```

1. Konfirmasikan bahwa informasi jenis media benar-benar ada. Jalankan:

   ```
   curl -v bucket-name/folder-name
   ```

   Output dari perintah ini harus menunjukkan informasi jenis media yang Anda tetapkan saat mengunggah file.

1. Kemudian Anda dapat menggunakan perintah `SPARQL UPDATE LOAD` untuk mengimpor file-file ini ke Neptune:

   ```
   curl https://your-neptune-endpoint:port/sparql \
     -d "update=LOAD <https://s3.amazonaws.com/bucket-name/my-rdf-input/test.rdf>"
   ```

Langkah-langkah di atas bekerja hanya untuk bucket Amazon S3 publik, atau untuk bucket yang Anda akses menggunakan [URL Amazon S3 pre-signed](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html) dalam kueri LOAD.

 Anda juga dapat mengatur server proksi web untuk memuat dari bucket Amazon S3 privat, seperti yang ditunjukkan di bawah ini:

**Menggunakan server web untuk memuat file ke Neptune dengan SPARQL UPDATE LOAD**

1. Instal server web pada mesin yang berjalan di dalam VPC yang menjadi host Neptune dan file yang akan dimuat. Misalnya, menggunakan Amazon Linux, Anda dapat menginstal Apache seperti berikut:

   ```
   sudo yum install httpd mod_ssl
   sudo /usr/sbin/apachectl start
   ```

1. Tentukan jenis MIME dari konten file RDF yang akan Anda muat. SPARQL menggunakan header `Content-type` yang dikirim oleh server web untuk menentukan format input konten, sehingga Anda harus menentukan jenis MIME yang relevan untuk Server web.

   Misalnya, misalkan Anda menggunakan ekstensi file berikut untuk mengidentifikasi format file:
   + `.nt`untuk NTriples.
   + `.nq`untuk NQuads.
   + `.trig` untuk Trig.
   + `.rdf` untuk RDF/XML.
   + `.ttl` untuk Turtle.
   + `.n3` untuk N3.
   + `.jsonld` untuk JSON-LD.

   Jika Anda menggunakan Apache 2 sebagai server web, Anda akan mengedit `/etc/mime.types` file dan menambahkan jenis berikut:

   ```
    text/plain nt
    application/n-quads nq
    application/trig trig
    application/rdf+xml rdf
    application/x-turtle ttl
    text/rdf+n3 n3
    application/ld+json jsonld
   ```

1. Konfirmasikan bahwa pemetaan tipe MIME bekerja. Setelah server web Anda aktif dan berjalan dan meng-hosting file RDF dalam format pilihan Anda, Anda dapat menguji konfigurasi dengan mengirimkan permintaan ke server web dari host lokal Anda.

   Misalnya, Anda dapat mengirim permintaan seperti ini:

   ```
   curl -v http://localhost:80/test.rdf
   ```

   Kemudian, dalam output detail dari `curl`, Anda akan melihat baris seperti:

   ```
   Content-Type: application/rdf+xml
   ```

   Hal ini menunjukkan bahwa pemetaan jenis konten dinyatakan berhasil.

1. Anda sekarang siap memuat data menggunakan perintah SPARQL UPDATE:

   ```
   curl https://your-neptune-endpoint:port/sparql \
       -d "update=LOAD <http://web_server_private_ip:80/test.rdf>"
   ```

**catatan**  
Menggunakan `SPARQL UPDATE LOAD` dapat memicu waktu henti pada server web ketika file sumber yang dimuat berukuran besar. Neptune memproses data file seperti data dialirkan masuk, dan untuk file besar yang dapat memakan waktu lebih lama dari batas waktu yang dikonfigurasi di server. Hal ini pada gilirannya dapat menyebabkan server untuk menutup koneksi, yang dapat mengakibatkan pesan kesalahan berikut ketika Neptune menemui EOF tak terduga di aliran:  

```
{
  "detailedMessage":"Invalid syntax in the specified file",
  "code":"InvalidParameterException"
}
```
Jika Anda menerima pesan ini dan tidak percaya bahwa file sumber berisi sintaks yang tidak valid, coba tingkatkan pengaturan batas waktu di server web. Anda juga dapat mendiagnosis masalah dengan mengaktifkan debug log di server dan mencari waktu henti.

# Menggunakan SPARQL UPDATE UNLOAD untuk menghapus data dari Neptune
<a name="sparql-api-reference-unload"></a>

Neptune juga menyediakan operasi SPARQL kustom, `UNLOAD`, untuk menghapus data yang ditentukan dalam sumber remote. `UNLOAD` dapat dianggap sebagai mitra untuk operasi `LOAD`. Sintaksnya adalah:

```
UNLOAD SILENT (URL of the remote data to be unloaded) FROM GRAPH (named graph from which to remove the data)
```
+ **`SILENT`**   –   (*Opsional*) Menyebabkan operasi mengembalikan sukses bahkan jika ada kesalahan selama pemrosesan data.

  Hal ini dapat berguna ketika transaksi tunggal berisi beberapa pernyataan seperti `"LOAD ...; LOAD ...; UNLOAD ...; LOAD ...;"` dan Anda ingin transaksinya selesai bahkan jika beberapa data jarak jauh tidak dapat diproses.
+ *URL of the remote data to be unloaded*— (*Wajib*) Menentukan file data jarak jauh yang berisi data yang akan diturunkan dari grafik.

  File jarak jauh harus memiliki salah satu ekstensi berikut (ini adalah format yang sama yang didukung UPDATE-LOAD):
  + `.nt`untuk NTriples.
  + `.nq`untuk NQuads.
  + `.trig` untuk Trig.
  + `.rdf` untuk RDF/XML.
  + `.ttl` untuk Turtle.
  + `.n3` untuk N3.
  + `.jsonld` untuk JSON-LD.

  Semua data yang berisi file ini akan dihapus dari klaster DB Anda oleh operasi `UNLOAD`.

  Otentikasi Amazon S3 harus disertakan dalam URL untuk data yang akan batal dimuat. Anda dapat melakukan pre-sign pada file Amazon S3 lalu menggunakan URL yang dihasilkan untuk mengaksesnya dengan aman. Contoh:

  ```
  aws s3 presign --expires-in (number of seconds) s3://(bucket name)/(path to file of data to unload)
  ```

  Kemudian:

  ```
  curl https://(a Neptune endpoint URL):8182/sparql \
    --data-urlencode 'update=unload (pre-signed URL of the remote Amazon S3 data to be unloaded) \
                             from graph (named graph)'
  ```

  Untuk informasi lebih lanjut, lihat [Melakukan Autentikasi Permintaan: Menggunakan Parameter Kueri](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html).
+ **`FROM GRAPH `***(named graph from which to remove the data)*— (*Opsional*) Menentukan grafik bernama dari mana data jarak jauh harus diturunkan.

  Neptune mengasosiasikan setiap tripel dengan grafik bernama. Anda dapat menentukan grafik bernama default menggunakan URI grafik bernama fallback, `http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph`, seperti ini:

  ```
  FROM GRAPH <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph>
  ```

Dengan cara yang sama saat `LOAD` sesuai dengan `INSERT DATA { (inline data) }`, `UNLOAD` sesuai dengan `DELETE DATA { (inline data) }`. Seperti halnya `DELETE DATA`, `UNLOAD` tidak berfungsi pada data yang berisi simpul kosong.

Sebagai contoh, jika server web lokal melayani file bernama `data.nt` yang berisi 2 triple berikut:

```
<http://example.org/resource#a> <http://example.org/resource#p> <http://example.org/resource#b> .
<http://example.org/resource#a> <http://example.org/resource#p> <http://example.org/resource#c> .
```

Perintah `UNLOAD` berikut akan menghapus dua triple tersebut dari grafik bernama, `<http://example.org/graph1>`:

```
UNLOAD <http://localhost:80/data.nt> FROM GRAPH <http://example.org/graph1>
```

Hal ini akan memiliki efek yang sama seperti menggunakan perintah `DELETE DATA` berikut:

```
DELETE DATA {
  GRAPH <http://example.org/graph1> {
    <http://example.org/resource#a> <http://example.org/resource#p> <http://example.org/resource#b> .
    <http://example.org/resource#a> <http://example.org/resource#p> <http://example.org/resource#c> .
  }
}
```

**Pengecualian yang dilemparkan oleh perintah `UNLOAD`**
+ **`InvalidParameterException`**   –   Ada simpul kosong dalam data. *Status HTTP*: 400 Permintaan Buruk.

  *Pesan*: ` Blank nodes are not allowed for UNLOAD`

   
+ **`InvalidParameterException`**   –   Ada sintaks yang rusak dalam data. *Status HTTP*: 400 Permintaan Buruk.

  *Pesan*: `Invalid syntax in the specified file.`

   
+ **`UnloadUrlAccessDeniedException `**   –   Akses ditolak. *Status HTTP*: 400 Permintaan Buruk.

  *Pesan*: `Update failure: Endpoint (Neptune endpoint) reported access denied error. Please verify access.`

   
+ **`BadRequestException `**   –   Data jarak jauh tidak dapat diambil. *Status HTTP*: 400 Permintaan Buruk.

  *Pesan*: *(tergantung respons HTTP).*

# Petunjuk kueri SPARQL
<a name="sparql-query-hints"></a>

Gunakan petunjuk kueri untuk menentukan optimasi dan evaluasi strategi untuk kueri SPARQL tertentu di Amazon Neptune. 

Petunjuk kueri dinyatakan menggunakan pola triple tambahan yang tertanam dalam kueri SPARQL dengan bagian-bagian berikut:

```
scope hint value
```
+ *lingkup* – Menentukan bagian dari kueri yang petunjuk kuerinya diberlakukan padanya, seperti grup tertentu dalam kueri atau kueri lengkap.
+ *petunjuk* – Mengidentifikasi jenis petunjuk yang akan diterapkan.
+ *nilai* – Menentukan perilaku aspek sistem yang sedang dipertimbangkan.

Petunjuk dan cakupan kueri dipaparkan sebagai istilah yang telah ditetapkan dalam namespace Amazon Neptune `http://aws.amazon.com/neptune/vocab/v01/QueryHints#`. Contoh dalam bagian ini menyertakan namespace sebagai awalan `hint` yang didefinisikan dan disertakan dalam kueri:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
```

Sebagai contoh, hal berikut ini menunjukkan bagaimana cara memasukkan petunjuk `joinOrder` dalam kueri `SELECT`:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT ... {
 hint:Query hint:joinOrder "Ordered" .
 ...
}
```

Kueri sebelumnya menginstruksikan mesin Neptune untuk mengevaluasi gabungan dalam kueri dalam urutan *yang diberikan* dan menonaktifkan pengurutan ulang otomatis apa pun.

Saat menggunakan petunjuk kueri, pertimbangkan hal berikut:
+ Anda dapat menggabungkan petunjuk kueri yang berbeda dalam satu kueri. Misalnya, Anda dapat menggunakan petunjuk kueri `bottomUp` untuk menganotasi subkueri untuk evaluasi bottom-up dan petunjuk kueri `joinOrder` untuk memperbaiki urutan gabungan dalam subkueri.
+ Anda dapat menggunakan petunjuk kueri yang sama beberapa kali, dalam cakupan yang tidak tumpang tindih yang berbeda.
+ Petunjuk kueri adalah petunjuk. Meskipun mesin kueri umumnya bertujuan untuk mempertimbangkan petunjuk kueri yang diberikan, mesin mungkin juga mengabaikannya.
+ Petunjuk kueri adalah pelestarian semantik. Menambahkan petunjuk kueri tidak mengubah output kueri (kecuali untuk urutan hasil potensial ketika tidak ada jaminan pengurutan yang diberikan—yaitu, ketika urutan hasil tidak secara eksplisit ditegakkan menggunakan ORDER BY). 

Bagian berikut menyediakan informasi selengkapnya tentang petunjuk kueri yang tersedia dan penggunaannya di Neptune.

**Topics**
+ [Cakupan petunjuk kueri SPARQL di Neptune](#sparql-query-hints-scope)
+ [Petunjuk kueri SPARQL `joinOrder`](sparql-query-hints-joinOrder.md)
+ [Petunjuk kueri SPARQL `evaluationStrategy`](sparql-query-hints-evaluationStrategy.md)
+ [Petunjuk kueri SPARQL `queryTimeout`](sparql-query-hints-queryTimeout.md)
+ [Petunjuk kueri SPARQL `rangeSafe`](sparql-query-hints-rangeSafe.md)
+ [Petunjuk Kueri SPARQL `queryId`](sparql-query-hints-queryId.md)
+ [Petunjuk kueri SPARQL `useDFE`](sparql-query-hints-useDFE.md)
+ [Petunjuk kueri SPARQL digunakan dengan DESCRIBE](sparql-query-hints-for-describe.md)

## Cakupan petunjuk kueri SPARQL di Neptune
<a name="sparql-query-hints-scope"></a>

Tabel berikut menampilkan cakupan yang tersedia, petunjuk terkait, dan deskripsi untuk petunjuk kueri SPARQL di Amazon Neptune. Awalan `hint` dalam entri ini mewakili namespace Neptune untuk petunjuk:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
```


| Lingkup | Petunjuk yang Didukung | Deskripsi | 
| --- | --- | --- | 
| hint:Query | [JoinOrder](sparql-query-hints-joinOrder.md) | Petunjuk kueri berlaku untuk seluruh kueri. | 
| hint:Query | [queryTimeout](sparql-query-hints-queryTimeout.md) | Nilai batas waktu berlaku untuk seluruh kueri. | 
| hint:Query | [rangeSafe](sparql-query-hints-rangeSafe.md) | Promosi jenis dinonaktifkan untuk seluruh kueri. | 
| hint:Query | [queryId](sparql-query-hints-queryId.md) | Nilai ID kueri berlaku untuk seluruh kueri. | 
| hint:Query | [useDFE](sparql-query-hints-useDFE.md) | Penggunaan DFE diaktifkan (atau dinonaktifkan) untuk seluruh kueri. | 
| hint:Group | [JoinOrder](sparql-query-hints-joinOrder.md) | Permintaan kueri berlaku untuk elemen tingkat atas dalam grup tertentu, tetapi tidak untuk elemen nested (seperti subkueri) atau elemen induk. | 
| hint:SubQuery | [evaluationStrategy](sparql-query-hints-evaluationStrategy.md) | Petunjuk ditentukan dan diterapkan untuk subkueri SELECT nested. Subkueri dievaluasi secara independen, tanpa mempertimbangkan solusi dihitung sebelum subkueri. | 

# Petunjuk kueri SPARQL `joinOrder`
<a name="sparql-query-hints-joinOrder"></a>

Ketika Anda mengirimkan kueri SPARQL, mesin kueri Amazon Neptune menyelidiki struktur kueri. Mesin tersebut mengurutkan ulang bagian dari kueri dan mencoba untuk meminimalkan jumlah pekerjaan yang diperlukan untuk evaluasi dan waktu respon kueri.

Misalnya, urutan pola tripel yang terhubung biasanya tidak dievaluasi dalam urutan yang diberikan. Urutan tersebut diurutkan ulang menggunakan heuristik dan statistik seperti selektivitas masing-masing pola dan bagaimana mereka terhubung melalui variabel bersama. Selain itu, jika kueri Anda berisi pola yang lebih kompleks seperti subkueri, FILTERs, atau blok OPSIONAL atau MINUS yang kompleks, mesin kueri Neptunus menyusun ulang jika memungkinkan, bertujuan untuk urutan evaluasi yang efisien.

Untuk kueri yang lebih kompleks, urutan di mana Neptune memilih untuk mengevaluasi kueri mungkin tidak selalu optimal. Misalnya, Neptune mungkin kehilangan karakteristik spesifik data instans (seperti mencapai node daya dalam grafik) yang muncul selama evaluasi kueri.

Jika Anda tahu karakteristik data yang tepat dan ingin secara manual mendikte urutan eksekusi kueri, gunakan petunjuk kueri `joinOrder` Neptune untuk menentukan bahwa kueri dievaluasi dalam urutan yang diberikan.

## Sintaks petunjuk SPARQ `joinOrder`
<a name="sparql-query-hints-joinOrder-syntax"></a>

Petunjuk kueri `joinOrder` ditentukan sebagai pola tripel yang disetakan dalam kueri SPARQL.

Untuk kejelasan, sintaks berikut menggunakan awalan `hint` yang didefinisikan dan disertakan dalam kueri untuk menentukan namespace petunjuk kueri Neptune:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
scope hint:joinOrder "Ordered" .
```

**Cakupan yang Tersedia**
+ `hint:Query`
+ `hint:Group`

Untuk informasi lebih lanjut tentang cakupan petunjuk kueri, lihat [Cakupan petunjuk kueri SPARQL di Neptune](sparql-query-hints.md#sparql-query-hints-scope).

## Contoh petunjuk SPARQL `joinOrder`
<a name="sparql-query-hints-joinOrder-example"></a>

Bagian ini menunjukkan kueri yang ditulis dengan dan tanpa petunjuk kueri `joinOrder` dan optimasi terkait.

Sebagai contoh, asumsikan bahwa set data berisi hal berikut ini:
+ Satu orang bernama `John` yang `:likes` 1.000 orang, termasuk `Jane`.
+ Satu orang bernama `Jane` yang `:likes` 10 orang, termasuk `John`.

**Tidak Ada Petunjuk Kueri**  
Kueri SPARQL berikut mengekstrak semua pasangan orang bernama `John` dan `Jane` yang saling menyukai satu sama lain dari satu set data jejaring sosial:

```
PREFIX : <https://example.com/>
SELECT ?john ?jane {
  ?person1 :name "Jane" .
  ?person1 :likes ?person2 .
  ?person2 :name "John" .
  ?person2 :likes ?person1 .
}
```

Mesin kueri Neptune mungkin mengevaluasi pernyataan dalam urutan yang berbeda dari yang ditulis. Sebagai contoh, mesin mungkin memilih untuk menilai dalam susunan berikut:

1. Temukan semua orang yang bernama `John`.

1. Temukan semua orang yang terhubung ke `John` berdasarkan edge `:likes`.

1. Saring set ini berdasarkan orang yang bernama `Jane`.

1. Saring set ini berdasarkan orang yang terhubung ke `John` berdasarkan edge `:likes`.

Menurut set data, mengevaluasi dalam urutan ini menghasilkan 1.000 entitas yang diekstraksi pada langkah kedua. Langkah ketiga mempersempit ini ke node tunggal, `Jane`. Langkah terakhir kemudian menentukan bahwa `Jane` juga `:likes` node `John`.

**Petunjuk Kueri**  
Akan menguntungkan untuk memulai dengan node `Jane` karena dia hanya memiliki 10 edge `:likes` keluar. Hal ini mengurangi jumlah pekerjaan selama evaluasi kueri dengan menghindari ekstraksi 1.000 entitas selama langkah kedua.

Contoh berikut menggunakan petunjuk kueri **JoinOrder** untuk memastikan bahwa node `Jane` dan edge keluarnya diproses terlebih dulu dengan menonaktifkan semua pengurutan ulang bergabung otomatis untuk kueri:

```
PREFIX : <https://example.com/>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT ?john ?jane {
  hint:Query hint:joinOrder "Ordered" .
  ?person1 :name "Jane" .
  ?person1 :likes ?person2 .
  ?person2 :name "John" .
  ?person2 :likes ?person1 .
}
```

Skenario dunia nyata yang berlaku mungkin berupa aplikasi jaringan sosial di mana orang-orang dalam jaringan diklasifikasikan sebagai influencer dengan banyak koneksi atau sebagai pengguna normal dengan beberapa koneksi. Dalam skenario seperti itu, Anda dapat memastikan bahwa pengguna normal (`Jane`) diproses sebelum influencer (`John`) dalam kueri seperti contoh sebelumnya.

**Petunjuk Kueri dan Pengurutan Ulang**  
Anda dapat mengolah contoh ini satu langkah lebih jauh. Jika Anda tahu bahwa atribut `:name` unik untuk node tunggal, Anda bisa mempercepat kueri dengan pengurutan ulang dan menggunakan petunjuk kueri `joinOrder`. Langkah ini memastikan bahwa node unik diekstraksi pertama.

```
PREFIX : <https://example.com/>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT ?john ?jane {
  hint:Query hint:joinOrder "Ordered" .
  ?person1 :name "Jane" .
  ?person2 :name "John" .
  ?person1 :likes ?person2 .
  ?person2 :likes ?person1 .
}
```

Dalam kasus ini, Anda dapat mengurangi kueri untuk tindakan tunggal berikut di setiap langkah:

1. Cari node satu orang dengan `:name` `Jane`.

1. Cari node satu orang dengan `:name` `John`.

1. Pastikan bahwa node pertama terhubung ke node kedua dengan edge `:likes`.

1. Pastikan bahwa node kedua terhubung ke node pertama dengan edge `:likes`.



**penting**  
Jika Anda memilih urutan yang salah, petunjuk kueri `joinOrder` dapat menyebabkan penurunan kinerja yang signifikan. Sebagai contoh, contoh sebelumnya akan menjadi tidak efisien jika atribut `:name` tidak unik. Jika semua 100 node diberi nama `Jane` dan semua 1.000 node diberi nama `John`, maka akhir kueri akan memeriksa 1.000 \$1 100 (100.000) pasang untuk edge `:likes`.

# Petunjuk kueri SPARQL `evaluationStrategy`
<a name="sparql-query-hints-evaluationStrategy"></a>

Petunjuk kueri `evaluationStrategy` untuk memberi tahu mesin Amazon Neptune bahwa fragmen kueri yang dianotasi harus dievaluasi dari bawah ke atas sebagai unit independen. Ini berarti bahwa tidak ada solusi dari langkah-langkah evaluasi sebelumnya yang digunakan untuk menghitung fragmen kueri. Fragmen kueri dievaluasi sebagai unit mandiri, dan solusi yang dihasilkan digabungkan dengan sisa kueri setelah dihitung.

Menggunakan petunjuk kueri `evaluationStrategy` menyiratkan rencana kueri (non-pipelined) pemblokiran, yang berarti bahwa solusi dari fragmen yang dianotasi dengan petunjuk kueri dimeterialisasikan dan di-buffer dalam memori utama. Menggunakan petunjuk kueri ini mungkin secara signifikan meningkatkan jumlah memori utama yang diperlukan untuk mengevaluasi kueri, terutama jika fragmen kueri yang dianotasi menghitung sejumlah besar hasil.

## Sintaks petunjuk SPARQ `evaluationStrategy`
<a name="sparql-query-hints-evaluationStrategy-syntax"></a>

Petunjuk kueri `evaluationStrategy` ditentukan sebagai pola tripel yang disetakan dalam kueri SPARQL.

Untuk kejelasan, sintaks berikut menggunakan awalan `hint` yang didefinisikan dan disertakan dalam kueri untuk menentukan namespace petunjuk kueri Neptune:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
hint:SubQuery hint:evaluationStrategy "BottomUp" .
```

**Cakupan yang Tersedia**
+ `hint:SubQuery`

**catatan**  
Petunjuk kueri ini didukung hanya dalam subqueries nested.

Untuk informasi lebih lanjut tentang cakupan petunjuk kueri, lihat [Cakupan petunjuk kueri SPARQL di Neptune](sparql-query-hints.md#sparql-query-hints-scope).

## Contoh petunjuk SPARQL `evaluationStrategy`
<a name="sparql-query-hints-evaluationStrategy-example"></a>



Bagian ini menunjukkan kueri yang ditulis dengan dan tanpa petunjuk kueri `evaluationStrategy` dan optimasi terkait.

Untuk contoh ini, anggaplah set data memiliki karakteristik sebagai berikut:
+ Berisi 1.000 edge berlabel `:connectedTo`.
+ Setiap node `component` terhubung ke rata-rata 100 node `component` lainnya.
+ Jumlah umum koneksi siklus empat hop antara node adalah sekitar 100.

Sebagai contoh umum, petunjuk `evaluationStrategy` dapat membantu mengoptimalkan pola kueri yang mengandung siklus.

**Tidak Ada Petunjuk Kueri**  
Kueri SPARQL berikut mengekstrak semua `component` node yang terhubung secara siklus satu sama lain melalui empat hop:

```
PREFIX : <https://example.com/>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * {
  ?component1 :connectedTo ?component2 .
  ?component2 :connectedTo ?component3 .
  ?component3 :connectedTo ?component4 .
  ?component4 :connectedTo ?component1 .
}
```

Pendekatan mesin kueri Neptune adalah mengevaluasi kueri ini menggunakan langkah-langkah berikut:
+ Ekstrak kesemua 1.000 edge `connectedTo` dalam grafik.
+ Perluas dengan 100x (jumlah edge `connectedTo` keluar dari component2).

  Hasil antara: 100.000 node.
+ Perluas dengan 100x (jumlah edge `connectedTo` keluar dari component3).

  Hasil antara: 10.000.000 node.
+ Pindai 10.000.000 node untuk siklus menutup.

Hal ini menyebabkan rencana kueri streaming, yang memiliki jumlah konstan memori utama.

**Petunjuk Kueri dan Subqueries**  
Anda mungkin ingin menukar ruang memori utama untuk komputasi yang lebih cepat. Dengan menulis ulang kueri menggunakan petunjuk kueri `evaluationStrategy`, Anda dapat memaksa mesin untuk menghitung gabungan antara dua subset kecil yang dimaterialisasi.

```
PREFIX : <https://example.com/>
          PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * {
  {
    SELECT * WHERE {
      hint:SubQuery hint:evaluationStrategy "BottomUp" .
      ?component1 :connectedTo ?component2 .
      ?component2 :connectedTo ?component3 .
    }
  }
  {
    SELECT * WHERE {
      hint:SubQuery hint:evaluationStrategy "BottomUp" .
      ?component3 :connectedTo ?component4 .
      ?component4 :connectedTo ?component1 .
    }
  }
}
```

Alih-alih mengevaluasi pola triple secara berurutan sembari secara iteratif menggunakan hasil dari pola triple sebelumnya sebagai input untuk pola yang akan datang, petunjuk `evaluationStrategy` menyebabkan dua subqueries dievaluasi secara independen. Kedua subqueries menghasilkan 100.000 node untuk hasil antara, yang kemudian digabungkan bersama-sama untuk membentuk output akhir. 

Secara khusus, ketika Anda menjalankan Neptune pada tipe instans yang lebih besar, menyimpan sementara kedua 100.000 subset ini dalam memori utama meningkatkan penggunaan memori sebagai akibat dari secara signifikan mempercepat evaluasi.

# Petunjuk kueri SPARQL `queryTimeout`
<a name="sparql-query-hints-queryTimeout"></a>

Petunjuk kueri `queryTimeout` menentukan batas waktu yang lebih pendek dari nilai `neptune_query_timeout` yang ditetapkan dalam grup parameter DB.

Jika kueri diakhiri sebagai hasil dari petunjuk ini, `TimeLimitExceededException` dilemparkan, dengan pesan `Operation terminated (deadline exceeded)`.

## Sintaks petunjuk SPARQ `queryTimeout`
<a name="sparql-query-hints-queryTimeout-syntax"></a>

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT ... WHERE {
    hint:Query hint:queryTimeout 10 .
    # OR
    hint:Query hint:queryTimeout "10" .
    # OR
    hint:Query hint:queryTimeout "10"^^xsd:integer .
 ...
}
```

Nilai batas waktu dinyatakan dalam milidetik.

Nilai batas waktu harus lebih kecil dari nilai `neptune_query_timeout` yang ditetapkan dalam grup parameter DB. Jika tidak, pengecualian `MalformedQueryException` dilemparkan dengan pesan `Malformed query: Query hint 'queryTimeout' must be less than neptune_query_timeout DB Parameter Group`.

Petunjuk kueri `queryTimeout` harus ditentukan dalam klausa `WHERE` dari kueri utama, atau dalam klausa `WHERE` dari salah satu subqueries seperti yang ditunjukkan pada contoh di bawah ini.

Ini harus diatur hanya sekali di semua bagian Pembaruan queries/subqueries dan SPARQL (seperti INSERT dan DELETE). Jika tidak, pengecualian `MalformedQueryException` dilemparkan dengan pesan `Malformed query: Query hint 'queryTimeout' must be set only once`.

**Cakupan yang Tersedia**

Petunjuk `queryTimeout` dapat diterapkan baik untuk kueri dan update SPARQL.
+ Dalam kueri SPARQL, petunjuk dapat muncul di klausa WHERE dari kueri utama atau subkueri.
+ Dalam update SPARQL, petunjuk dapat diatur dalam klausa INSERT, DELETE, atau WHERE. Jika ada beberapa klausa pembaruan, petunjuk hanya dapat diatur dalam salah satu dari klausa tersebut.

Untuk informasi lebih lanjut tentang cakupan petunjuk kueri, lihat [Cakupan petunjuk kueri SPARQL di Neptune](sparql-query-hints.md#sparql-query-hints-scope).

## Contoh petunjuk SPARQL `queryTimeout`
<a name="sparql-query-hints-queryTimeout-example"></a>

Berikut adalah contoh penggunaan `hint:queryTimeout` di klausa `WHERE` utama dari kueri `UPDATE`:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
INSERT {
    ?s ?p ?o
} WHERE {
    hint:Query hint:queryTimeout 100 .
    ?s ?p ?o .
}
```

Di sini, `hint:queryTimeout` berada di klausa `WHERE` dari subkueri:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * {
   ?s ?p ?o .
   {
      SELECT ?s WHERE {
         hint:Query hint:queryTimeout 100 .
         ?s ?p1 ?o1 .
      }
   }
}
```

# Petunjuk kueri SPARQL `rangeSafe`
<a name="sparql-query-hints-rangeSafe"></a>

Gunakan petunjuk kueri ini untuk menonaktifkan promosi jenis untuk kueri SPARQL.

Ketika Anda mengirimkan kueri SPARQL yang mencakup `FILTER` di atas nilai atau jangkauan numerik, mesin kueri Neptune biasanya harus menggunakan promosi jenis ketika mengeksekusi kueri. Ini berarti bahwa mesin harus memeriksa nilai-nilai dari setiap jenis yang dapat memegang nilai yang Anda gunakan untuk menyaring.

Misalnya, jika Anda menyaring untuk nilai yang sama dengan 55, mesin harus mencari bilangan bulat yang sama dengan 55, bilangan bulat panjang sama dengan 55L, mengapung sama dengan 55.0, dan sebagainya. Setiap jenis promosi memerlukan pencarian tambahan pada penyimpanan, yang dapat menyebabkan permintaan yang tampaknya sederhana tiba-tiba mengambil waktu yang lama untuk menyelesaikan.

Sering kali promosi jenis tidak perlu karena Anda tahu sebelumnya bahwa Anda hanya perlu menemukan nilai dari satu jenis tertentu. Ketika hal ini terjadi, Anda dapat mempercepat kueri Anda secara dramatis dengan menggunakan petunjuk kueri `rangeSafe` untuk mematikan promosi jenis.

## Sintaks petunjuk SPARQ `rangeSafe`
<a name="sparql-query-hints-rangeSafe-syntax"></a>

Petunjuk kueri `rangeSafe` mengambil nilai `true` untuk menonaktifkan promosi jenis. Hal ini juga menerima nilai `false` (default).

**Contoh.** Contoh berikut menunjukkan bagaimana untuk mematikan promosi jenis ketika penyaringan untuk nilai integer dari `o` lebih besar dari 1:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * {
   ?s ?p ?o .
   hint:Prior hint:rangeSafe 'true' .
   FILTER (?o > '1'^^<http://www.w3.org/2001/XMLSchema#int>)
```

# Petunjuk Kueri SPARQL `queryId`
<a name="sparql-query-hints-queryId"></a>

Gunakan petunjuk kueri ini untuk menetapkan nilai queriId Anda sendiri ke kueri SPARQL.

Contoh:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * WHERE {
  hint:Query hint:queryId "4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47"
  {?s ?p ?o}}
```

Nilai yang Anda tetapkan harus unik di semua kueri di Neptune DB.

# Petunjuk kueri SPARQL `useDFE`
<a name="sparql-query-hints-useDFE"></a>

Gunakan petunjuk kueri ini untuk mengaktifkan penggunaan DFE untuk mengeksekusi kueri. [Secara default Neptunus tidak menggunakan DFE tanpa petunjuk kueri ini disetel ke, karena parameter instance neptune\$1dfe\$1query\$1engine default `true` ke.](parameters.md#parameters-instance-parameters-neptune_dfe_query_engine) `viaQueryHint` Jika Anda menyetel parameter instance itu`enabled`, mesin DFE digunakan untuk semua kueri kecuali yang memiliki petunjuk `useDFE` kueri yang disetel ke. `false`

Contoh mengaktifkan penggunaan DFE untuk kueri:

```
PREFIX : <https://example.com/>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>

SELECT ?john ?jane
{
  hint:Query hint:useDFE true .
  ?person1 :name "Jane" .
  ?person1 :likes ?person2 .
  ?person2 :name "John" .
  ?person2 :likes ?person1 .
}
```

# Petunjuk kueri SPARQL digunakan dengan DESCRIBE
<a name="sparql-query-hints-for-describe"></a>

`DESCRIBE`Kueri SPARQL menyediakan mekanisme yang fleksibel untuk meminta deskripsi sumber daya. Namun, spesifikasi SPARQL tidak menentukan semantik yang tepat dari. `DESCRIBE`

Dimulai dengan [rilis mesin 1.2.0.2](engine-releases-1.2.0.2.md), Neptunus mendukung beberapa `DESCRIBE` mode dan algoritma berbeda yang cocok untuk situasi yang berbeda.

Dataset sampel ini dapat membantu mengilustrasikan mode yang berbeda:

```
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix : <https://example.com/> .

:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JohnDoe :firstName "John" .
:JaneDoe :knows _:b1 .
_:b1 :knows :RichardRoe .

:RichardRoe :knows :JaneDoe .
:RichardRoe :firstName "Richard" .

_:s1 rdf:type rdf:Statement .
_:s1 rdf:subject :JaneDoe .
_:s1 rdf:predicate :knows .
_:s1 rdf:object :JohnDoe .
_:s1 :knowsFrom "Berlin" .

:ref_s2 rdf:type rdf:Statement .
:ref_s2 rdf:subject :JaneDoe .
:ref_s2 rdf:predicate :knows .
:ref_s2 rdf:object :JohnDoe .
:ref_s2 :knowsSince 1988 .
```

Contoh di bawah ini mengasumsikan bahwa deskripsi sumber daya `:JaneDoe` diminta menggunakan kueri SPARQL seperti ini:

```
DESCRIBE <https://example.com/JaneDoe>
```

## Petunjuk kueri SPARQL `describeMode`
<a name="sparql-query-hints-describeMode"></a>

Petunjuk kueri `hint:describeMode` SPARQL digunakan untuk memilih salah satu mode `DESCRIBE` SPARQL berikut yang didukung oleh Neptunus:

### Mode `ForwardOneStep` DESCRIPTE
<a name="sparql-query-hints-describeMode-ForwardOneStep"></a>

Anda menjalankan `ForwardOneStep` mode dengan petunjuk `describeMode` kueri seperti ini:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE <https://example.com/JaneDoe>
{
  hint:Query hint:describeMode "ForwardOneStep"
}
```

`ForwardOneStep`Mode hanya mengembalikan atribut dan tautan penerusan sumber daya yang akan dijelaskan. Dalam kasus contoh, ini berarti mengembalikan tiga kali lipat yang memiliki`:JaneDoe`, sumber daya yang akan dijelaskan, sebagai subjek:

```
:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JaneDoe :knows _:b301990159 .
```

Perhatikan bahwa kueri DESCRIBE dapat mengembalikan tiga kali lipat dengan node kosong, seperti`_:b301990159`, yang berbeda IDs setiap kali, dibandingkan dengan kumpulan data input.

### Mode `SymmetricOneStep` DESCRIPTE
<a name="sparql-query-hints-describeMode-SymmetricOneStep"></a>

`SymmetricOneStep`adalah mode DESCRIBE default jika Anda tidak memberikan petunjuk kueri. Anda juga dapat memanggilnya secara eksplisit dengan petunjuk `describeMode` kueri seperti ini:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE <https://example.com/JaneDoe>
{
  hint:Query hint:describeMode "SymmetricOneStep"
}
```

Di bawah `SymmetricOneStep` semantik, `DESCRIBE` mengembalikan atribut, tautan maju, dan tautan balik sumber daya yang akan dijelaskan:

```
:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JaneDoe :knows _:b318767375 .

_:b318767631 rdf:subject :JaneDoe .

:RichardRoe :knows :JaneDoe .

:ref_s2 rdf:subject :JaneDoe .
```

### Deskripsi Terbatas Ringkas (`CBD`) mode DESCRIPTION
<a name="sparql-query-hints-describeMode-CBD"></a>

Mode Concise Bounded Description (`CBD`) dipanggil menggunakan petunjuk `describeMode` kueri seperti ini:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE <https://example.com/JaneDoe>
{
  hint:Query hint:describeMode "CBD"
}
```

Di bawah `CBD` semantik, `DESCRIBE` mengembalikan Deskripsi Terbatas Ringkas (seperti yang [didefinisikan oleh W3C](http://www.w3.org/Submission/CBD)) dari sumber daya yang akan dijelaskan:

```
:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JaneDoe :knows _:b285212943 .
_:b285212943 :knows :RichardRoe .

_:b285213199 rdf:subject :JaneDoe .
_:b285213199 rdf:type rdf:Statement .
_:b285213199 rdf:predicate :knows .
_:b285213199 rdf:object :JohnDoe .
_:b285213199 :knowsFrom "Berlin" .

:ref_s2 rdf:subject :JaneDoe .
```

Deskripsi Terbatas Ringkas dari sumber daya RDF (yaitu, simpul dalam grafik RDF) adalah subgraf terkecil yang berpusat di sekitar node yang dapat berdiri sendiri. Dalam praktiknya ini berarti bahwa jika Anda menganggap grafik ini sebagai pohon, dengan simpul yang ditunjuk sebagai akar, tidak ada simpul kosong (bnode) sebagai daun pohon itu. Karena bnodes tidak dapat ditangani secara eksternal atau digunakan dalam kueri berikutnya, itu tidak cukup untuk menelusuri grafik hanya untuk menemukan hop tunggal berikutnya dari node saat ini. Anda juga harus pergi cukup jauh untuk menemukan sesuatu yang dapat digunakan dalam kueri berikutnya (yaitu, sesuatu selain bnode).

#### Menghitung CBD
<a name="sparql-query-hints-describeMode-CBD-computing"></a>

Diberikan node tertentu (node awal atau root) dalam grafik RDF sumber, CBD dari node tersebut dihitung sebagai berikut:

1. Sertakan dalam subgraf semua pernyataan dalam grafik sumber di mana *subjek* pernyataan adalah simpul awal.

1. Secara rekursif, untuk semua pernyataan dalam subgraf sejauh ini yang memiliki *objek* simpul kosong, sertakan dalam subgraf semua pernyataan dalam grafik sumber di mana *subjek* pernyataan adalah simpul kosong, dan yang belum termasuk dalam subgraf.

1. Secara rekursif, untuk semua pernyataan yang termasuk dalam subgraf sejauh ini, untuk semua reifikasi pernyataan ini dalam grafik sumber, sertakan CBD yang dimulai dari simpul setiap reifikasi. `rdf:Statement`

Ini menghasilkan subgraf di mana node *objek* adalah referensi IRI atau literal, atau node kosong yang tidak berfungsi sebagai *subjek* dari pernyataan apa pun dalam grafik. Perhatikan bahwa CBD tidak dapat dihitung menggunakan kueri SPARQL SELECT atau CONSTRUCT tunggal.

### Deskripsi Terbatas Ringkas Simetris () mode DESCRIBE `SCBD`
<a name="sparql-query-hints-describeMode-SCBD"></a>

Mode Symmetric Concise Bounded Description (`SCBD`) dipanggil menggunakan petunjuk `describeMode` kueri seperti ini:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE <https://example.com/JaneDoe>
{
  hint:Query hint:describeMode "SCBD"
}
```

Di bawah `SCBD` semantik, `DESCRIBE` mengembalikan Deskripsi Terbatas Ringkas Simetris dari sumber daya (seperti yang didefinisikan oleh W3C dalam [Menjelaskan](http://www.w3.org/TR/void/) Kumpulan Data Tertaut dengan Kosakata VoID:

```
:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JaneDoe :knows _:b335544591 .
_:b335544591 :knows :RichardRoe .

:RichardRoe :knows :JaneDoe .

_:b335544847 rdf:subject :JaneDoe .
_:b335544847 rdf:type rdf:Statement .
_:b335544847 rdf:predicate :knows .
_:b335544847 rdf:object :JohnDoe .
_:b335544847 :knowsFrom "Berlin" .

:ref_s2 rdf:subject :JaneDoe .
```

Keuntungan CBD dan SCBD dibandingkan `SymmetricOneStep` mode `ForwardOneStep` dan adalah bahwa node kosong selalu diperluas untuk memasukkan representasi mereka. Ini mungkin merupakan keuntungan penting karena Anda tidak dapat menanyakan simpul kosong menggunakan SPARQL. Selain itu, mode CBD dan SCBD juga mempertimbangkan reifikasi.

Perhatikan bahwa petunjuk `describeMode` kueri juga dapat menjadi bagian dari `WHERE` klausa:

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE ?s
WHERE {
  hint:Query hint:describeMode "CBD" .
  ?s rdf:type <https://example.com/Person>
}
```

## Petunjuk kueri SPARQL `describeIterationLimit`
<a name="sparql-query-hints-describeIterationLimit"></a>

Petunjuk kueri `hint:describeIterationLimit` SPARQL memberikan batasan **opsional** pada jumlah maksimum ekspansi berulang yang akan dilakukan untuk algoritme DESCRIBE berulang seperti CBD dan SCBD.

Batas DESKRIPSIKAN adalah ANDed bersama-sama. Oleh karena itu, jika batas iterasi dan batas pernyataan ditentukan, maka kedua batas harus dipenuhi sebelum kueri DESCRIBE terputus.

Default untuk nilai ini adalah 5. Anda dapat mengaturnya ke NOL (0) untuk menentukan NO limit pada jumlah ekspansi iteratif.

## Petunjuk kueri SPARQL `describeStatementLimit`
<a name="sparql-query-hints-describeStatementLimit"></a>

Petunjuk kueri `hint:describeStatementLimit` SPARQL memberikan kendala **opsional** pada jumlah maksimum pernyataan yang mungkin ada dalam respons kueri DESCRIBE. Ini hanya diterapkan untuk algoritma DESCRIBE berulang seperti CBD dan SCBD.

Batas DESKRIPSIKAN adalah ANDed bersama-sama. Oleh karena itu, jika batas iterasi dan batas pernyataan ditentukan, maka kedua batas harus dipenuhi sebelum kueri DESCRIBE terputus.

Default untuk nilai ini adalah 5000. Anda dapat mengaturnya ke NOL (0) untuk menentukan NO limit pada jumlah pernyataan yang dikembalikan.

# Perilaku DESKRIPSI SPARQL sehubungan dengan grafik default
<a name="sparql-default-describe"></a>

Formulir [https://www.w3.org/TR/sparql11-query/#describe](https://www.w3.org/TR/sparql11-query/#describe)kueri SPARQL memungkinkan Anda mengambil informasi tentang sumber daya tanpa mengetahui struktur data dan tanpa harus membuat kueri. Bagaimana informasi ini dirakit diserahkan kepada implementasi SPARQL. Neptunus [menyediakan beberapa petunjuk kueri](sparql-query-hints-for-describe.md) yang memanggil mode dan algoritma yang berbeda untuk digunakan. `DESCRIBE`

Dalam implementasi Neptunus, terlepas dari modenya, `DESCRIBE` hanya menggunakan data yang ada dalam grafik default [SPARQL](feature-sparql-compliance.md#sparql-default-graph). Ini konsisten dengan cara SPARQL memperlakukan kumpulan data (lihat [Menentukan Kumpulan Data RDF](https://www.w3.org/TR/sparql11-query/#specifyingDataset) dalam spesifikasi SPARQL).

Di Neptunus, grafik default berisi semua tripel unik dalam penyatuan semua grafik bernama dalam database, kecuali grafik bernama tertentu ditentukan menggunakan klausa. `FROM` and/or `FROM NAMED` Semua data RDF di Neptunus disimpan dalam grafik bernama. Jika rangkap tiga dimasukkan tanpa konteks grafik bernama, Neptunus menyimpannya dalam grafik bernama yang ditunjuk. `http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph`

Ketika satu atau beberapa grafik bernama ditentukan menggunakan `FROM` klausa, grafik default adalah gabungan dari semua tiga kali lipat unik dalam grafik bernama tersebut. Jika tidak ada `FROM` klausa dan ada satu atau lebih `FROM NAMED` klausa, maka grafik default kosong.

## Contoh `DESCRIBE` SPARQL
<a name="sparql-default-describe-examples"></a>

Pertimbangkan data berikut:

```
PREFIX ex: <https://example.com/>

GRAPH ex:g1 {
    ex:s ex:p1 "a" .
    ex:s ex:p2 "c" .
}

GRAPH ex:g2 {
    ex:s ex:p3 "b" .
    ex:s ex:p2 "c" .
}

ex:s ex:p3 "d" .
```

Untuk kueri ini:

```
PREFIX ex: <https://example.com/>
DESCRIBE ?s
FROM ex:g1
FROM NAMED ex:g2
WHERE {
  GRAPH ex:g2 { ?s ?p "b" . }
}
```

Neptunus akan kembali:

```
ex:s ex:p1 "a" .
ex:s ex:p2 "c" .
```

Di sini, pola grafik `GRAPH ex:g2 { ?s ?p "b" }` dievaluasi terlebih dahulu, menghasilkan binding untuk`?s`, dan kemudian `DESCRIBE` bagian tersebut dievaluasi melalui grafik default, yang sekarang hanya. `ex:g1`

Namun, untuk kueri ini:

```
PREFIX ex: <https://example.com/>
DESCRIBE ?s 
FROM NAMED ex:g1 
WHERE { 
  GRAPH ex:g1 { ?s ?p "a" . } 
}
```

Neptunus tidak akan mengembalikan apa pun, karena ketika `FROM NAMED` klausa hadir tanpa klausa apa `FROM` pun, grafik default kosong.

Dalam query berikut, `DESCRIBE` digunakan dengan no `FROM` atau `FROM NAMED` klausa hadir:

```
PREFIX ex: <https://example.com/>
DESCRIBE ?s 
WHERE { 
  GRAPH ex:g1 { ?s ?p "a" . } 
}
```

Dalam situasi ini, grafik default terdiri dari semua tiga kali lipat unik dalam penyatuan semua grafik bernama dalam database (secara formal, penggabungan RDF), sehingga Neptunus akan kembali:

```
ex:s ex:p1 "a" . 
ex:s ex:p2 "c" . 
ex:s ex:p3 "b" .
ex:s ex:p3 "d" .
```

# API status kueri SPARQL
<a name="sparql-api-status"></a>

Untuk mendapatkan status kueri SPARQL, gunakan HTTP `GET` atau `POST` untuk membuat permintaan ke titik akhir `https://your-neptune-endpoint:port/sparql/status`. 

## Parameter permintaan status kueri SPARQL
<a name="sparql-api-status-get-request"></a>

**queryId (opsional)**  
ID dari kueri SPARQL yang berjalan. Hanya menampilkan status kueri yang ditentukan.

## Sintaks respons status kueri SPARQL
<a name="sparql-api-status-get-response-syntax"></a>

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

## Nilai respons status kueri SPARQL
<a name="sparql-api-status-get-response-values"></a>

**acceptedQueryCount**  
Jumlah kueri yang diterima sejak restart terakhir mesin Neptune.

**runningQueryCount**  
Jumlah kueri SPARQL yang sedang berjalan.

**pertanyaan**  
Daftar kueri SPARQL saat ini.

**queryId**  
id GUID untuk kueri. Neptune secara otomatis memberikan nilai ID ini ke setiap kueri, atau Anda juga dapat menetapkan ID Anda sendiri (lihat [Menyuntikkan ID Kustom Ke Dalam Gremlin Neptune atau Kueri SPARQL](features-query-id.md)). 

**queryEvalStats**  
Statistik untuk kueri ini.

**subkueri**  
Jumlah subkueri dalam kueri ini.

**berlalu**  
Jumlah milidetik kueri telah berjalan sejauh ini.

**dibatalkan**  
True menunjukkan bahwa kueri dibatalkan.

**queryString**  
Kueri yang diajukan.

## Contoh status kueri SPARQL
<a name="sparql-api-status-get-example"></a>

Berikut ini adalah contoh perintah status menggunakan `curl` dan `GET` HTTP.

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

Output ini menunjukkan satu kueri yang berjalan.

```
{
    "acceptedQueryCount":9,
    "runningQueryCount":1,
    "queries": [
        {
            "queryId":"fb34cd3e-f37c-4d12-9cf2-03bb741bf54f",
            "queryEvalStats":
                {
                    "subqueries": 0,
                    "elapsed": 29256,
                    "cancelled": false
                },
            "queryString": "SELECT ?s ?p ?o WHERE {?s ?p ?o}"
        }
    ]
}
```

# Pembatalan kueri SPARQL
<a name="sparql-api-status-cancel"></a>

Untuk mendapatkan status kueri SPARQL, gunakan HTTP `GET` atau `POST` untuk membuat permintaan ke titik akhir `https://your-neptune-endpoint:port/sparql/status`.

## Parameter permintaan pembatalan kueri SPARQL
<a name="sparql-api-status-cancel-request"></a>

**CancelQuery**  
(Diperlukan) Memberi tahu perintah status untuk membatalkan kueri. Parameter ini tidak mengambil nilai.

**queryId**  
(Diperlukan) ID dari kueri SPARQL yang berjalan yang akan dibatalkan.

**diam**  
(Opsional) Jika `silent=true` maka kueri yang berjalan dibatalkan dan kode respon HTTPnya adalah 200. Jika `silent` tidak ada atau `silent=false`, kueri dibatalkan dengan kode status HTTP 500.

## Contoh pembatalan kueri SPARQL
<a name="sparql-api-status-cancel-example"></a>

**Contoh 1: Pembatalan dengan `silent=false`**  
Berikut ini adalah contoh perintah status menggunakan `curl` untuk membatalkan kueri dengan parameter `silent` diatur ke `false`:

```
curl https://your-neptune-endpoint:port/sparql/status \
  -d "cancelQuery" \
  -d "queryId=4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47" \
  -d "silent=false"
```

Kecuali kueri sudah mulai men-streaming hasil, kueri yang dibatalkan kemudian akan mengembalikan kode HTTP 500 dengan respons seperti ini:

```
{
  "code": "CancelledByUserException",
  "requestId": "4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47",
  "detailedMessage": "Operation terminated (cancelled by user)"
}
```

Jika kueri sudah mengembalikan kode HTTP 200 (OK) dan telah mulai men-streaming hasil sebelum dibatalkan, informasi pengecualian batas waktu dikirim ke stream output biasa.

**Contoh 2: Pembatalan dengan `silent=true`**  
Berikut ini adalah contoh dari perintah status yang sama seperti di atas kecuali dengan parameter `silent` sekarang diatur ke `true`:

```
curl https://your-neptune-endpoint:port/sparql/status \
  -d "cancelQuery" \
  -d "queryId=4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47" \
  -d "silent=true"
```

Perintah ini akan mengembalikan respons yang sama seperti ketika `silent=false`, tetapi kueri yang dibatalkan sekarang akan mengembalikan kode HTTP 200 dengan respons seperti ini:

```
{
  "head" : {
    "vars" : [ "s", "p", "o" ]
  },
  "results" : {
    "bindings" : [ ]
  }
}
```

# Menggunakan Protokol HTTP (GSP) SPARQL 1.1 Graph Store di Amazon Neptunus
<a name="sparql-graph-store-protocol"></a>

Dalam rekomendasi [Protokol HTTP SPARQL 1.1 Graph Store](https://www.w3.org/TR/sparql11-http-rdf-update/), W3C mendefinisikan protokol HTTP untuk mengelola grafik RDF. Ini mendefinisikan operasi untuk menghapus, membuat, dan mengganti konten grafik RDF serta untuk menambahkan pernyataan RDF ke konten yang ada.

Protokol graph-store (GSP) menyediakan cara mudah untuk memanipulasi seluruh grafik Anda tanpa harus menulis kueri SPARQL yang kompleks.

Neptunus sepenuhnya mendukung protokol ini.

Titik akhir untuk protokol graph-store (GSP) adalah:

```
https://your-neptune-cluster:port/sparql/gsp/
```

Untuk mengakses grafik default dengan GSP, gunakan:

```
https://your-neptune-cluster:port/sparql/gsp/?default
```

Untuk mengakses grafik bernama dengan GSP, gunakan:

```
https://your-neptune-cluster:port/sparql/gsp/?graph=named-graph-URI
```

## Detail khusus implementasi GSP Neptunus
<a name="sparql-graph-store-protocol-special"></a>

Neptunus sepenuhnya mengimplementasikan rekomendasi [W3C yang](https://www.w3.org/TR/sparql11-http-rdf-update/) mendefinisikan GSP. Namun, ada beberapa situasi yang spesifikasi tidak mencakup.

Salah satunya adalah kasus di mana `POST` permintaan `PUT` atau menentukan satu atau beberapa grafik bernama di badan permintaan yang berbeda dari grafik yang ditentukan oleh URL permintaan. Ini hanya dapat terjadi ketika format RDF badan permintaan mendukung grafik bernama, seperti, misalnya, menggunakan atau. `Content-Type: application/n-quads` `Content-Type: application/trig`

Dalam situasi ini, Neptunus menambahkan atau memperbarui semua grafik bernama yang ada di tubuh, serta grafik bernama yang ditentukan dalam URL.

Misalnya, misalkan dimulai dengan database kosong, Anda mengirim `PUT` permintaan untuk meningkatkan suara menjadi tiga grafik. Satu, bernama`urn:votes`, berisi semua suara dari semua tahun pemilihan. Dua lainnya, bernama `urn:votes:2005` dan`urn:votes:2019`, berisi suara dari tahun pemilihan tertentu. Permintaan dan muatannya terlihat seperti ini:

```
PUT "http://your-Neptune-cluster:port/sparql/gsp/?graph=urn:votes"
  Host: example.com
  Content-Type: application/n-quads

  PAYLOAD:

  <urn:JohnDoe> <urn:votedFor> <urn:Labour> <urn:votes:2005>
  <urn:JohnDoe> <urn:votedFor> <urn:Conservative> <urn:votes:2019>
  <urn:JaneSmith> <urn:votedFor> <urn:LiberalDemocrats> <urn:votes:2005>
  <urn:JaneSmith> <urn:votedFor> <urn:Conservative> <urn:votes:2019>
```

Setelah permintaan dijalankan, data dalam database terlihat seperti ini:

```
<urn:JohnDoe>   <urn:votedFor> <urn:Labour>           <urn:votes:2005>
<urn:JohnDoe>   <urn:votedFor> <urn:Conservative>     <urn:votes:2019>
<urn:JaneSmith> <urn:votedFor> <urn:LiberalDemocrats> <urn:votes:2005>
<urn:JaneSmith> <urn:votedFor> <urn:Conservative>     <urn:votes:2019>
<urn:JohnDoe>   <urn:votedFor> <urn:Labour>           <urn:votes>
<urn:JohnDoe>   <urn:votedFor> <urn:Conservative>     <urn:votes>
<urn:JaneSmith> <urn:votedFor> <urn:LiberalDemocrats> <urn:votes>
<urn:JaneSmith> <urn:votedFor> <urn:Conservative>     <urn:votes>
```

Situasi ambigu lainnya adalah di mana lebih dari satu grafik ditentukan dalam URL permintaan itu sendiri, menggunakan salah satu dari`PUT`,`POST`, `GET` atau. `DELETE` Contoh:

```
POST "http://your-Neptune-cluster:port/sparql/gsp/?graph=urn:votes:2005&graph=urn:votes:2019"
```

Atau:

```
GET "http://your-Neptune-cluster:port/sparql/gsp/?default&graph=urn:votes:2019"
```

Dalam situasi ini, Neptunus mengembalikan HTTP 400 dengan pesan yang menunjukkan bahwa hanya satu grafik yang dapat ditentukan dalam URL permintaan.

# Menganalisis eksekusi kueri Neptune menggunakan `explain` SPARQL
<a name="sparql-explain"></a>

Amazon Neptune telah menambahkan fitur SPARQL bernama *explain*. Fitur ini adalah alat swalayan untuk memahami pendekatan eksekusi yang diambil oleh mesin Neptune. Anda meminta dengan menambahkan parameter `explain` ke panggilan HTTP yang mengirimkan kueri SPARQL.

Fitur `explain` menyediakan informasi tentang struktur logis rencana eksekusi kueri. Anda dapat menggunakan informasi ini untuk mengidentifikasi potensi hambatan evaluasi dan eksekusi. Anda kemudian dapat menggunakan [petunjuk kueri](sparql-query-hints.md) untuk meningkatkan rencana eksekusi kueri Anda.

**Topics**
+ [Memahami bagaimana mesin kueri SPARQL Neptune bekerja.](sparql-explain-engine.md)
+ [Cara menggunakan `explain` SPARQL untuk menganalisis eksekusi kueri Neptune](sparql-explain-using.md)
+ [Contoh `explain` SPARQL yang dipanggil di Neptune](sparql-explain-examples.md)
+ [Operator `explain` SPARQL Neptune](sparql-explain-operators.md)
+ [Keterbatasan `explain` SPARQL di Neptune](sparql-explain-limitations.md)

# Memahami bagaimana mesin kueri SPARQL Neptune bekerja.
<a name="sparql-explain-engine"></a>

Untuk menggunakan informasi yang disediakan fitur `explain` SPARQL, Anda perlu memahami beberapa rincian tentang cara mesin kueri Amazon Neptune SPARQL bekerja.

Mesin menerjemahkan setiap kueri SPARQL ke dalam alur operator. Mulai dari operator pertama, solusi perantara yang dikenal sebagai *daftar pengikatan* mengalir melalui alur operator ini. Anda dapat memikirkan daftar pengikatan sebagai tabel di mana header tabel adalah bagian dari variabel yang digunakan dalam kueri. Setiap baris dalam tabel mewakili hasil, sampai titik evaluasi.

Mari kita asumsikan bahwa dua prefiks namespace telah didefinisikan untuk data kami:

```
  @prefix ex:   <http://example.com> .
  @prefix foaf: <http://xmlns.com/foaf/0.1/> .
```

Berikut ini akan menjadi contoh dari daftar pengikatan sederhana dalam konteks ini:

```
  ?person       | ?firstName
  ------------------------------------------------------
  ex:JaneDoe    | "Jane"
  ex:JohnDoe    | "John"
  ex:RichardRoe | "Richard"
```

Untuk masing-masing dari tiga orang, daftar tersebut mengikat variabel `?person` ke pengenal dari orang tersebut, dan variabel `?firstName` ke nama depat orang tersebut.

Dalam kasus umum, variabel dapat tetap tidak terikat, jika, misalnya, ada pemilihan `OPTIONAL` variabel dalam kueri yang tanpa nilai dalam data.

Operator `PipelineJoin` adalah contoh dari operator mesin kueri Neptune yang ada dalam output `explain`. Operator tersebut dibutuhkan sebagai set mengikat masuk dari operator sebelumnya dan bergabung dengan pola triple, misalnya `(?person, foaf:lastName, ?lastName)`. Operasi ini menggunakan pengikatan untuk variabel `?person` dalam stream inputnya, menggantikannya ke dalam pola triple, dan mencari triple dari database.

Ketika dieksekusi dalam konteks pengikatan masuk dari tabel sebelumnya, `PipelineJoin`akan mengevaluasi tiga pencarian, yaitu berikut ini:

```
  (ex:JaneDoe,    foaf:lastName, ?lastName)
  (ex:JohnDoe,    foaf:lastName, ?lastName)
  (ex:RichardRoe, foaf:lastName, ?lastName)
```

Pendekatan ini disebut evaluasi *as-bound*. Solusi dari proses evaluasi ini digabungkan kembali dengan solusi yang masuk, mengalasi `?lastName` yang terdeteksi dalam solusi yang masuk. Dengan asumsi bahwa Anda menemukan nama terakhir untuk ketiga orang tersebut, operator akan menghasilkan daftar mengikat keluar yang akan terlihat seperti ini:

```
  ?person       | ?firstName | ?lastName
  ---------------------------------------
  ex:JaneDoe    | "Jane"     | "Doe"
  ex:JohnDoe    | "John"     | "Doe"
  ex:RichardRoe | "Richard"  | "Roe"
```

Daftar mengikat keluar ini kemudian berfungsi sebagai input untuk operator berikutnya dalam alur. Pada akhirnya, output dari operator terakhir dalam alur mendefinisikan hasil kueri.

Alur operator sering linier, dalam arti bahwa setiap operator mengeluarkan solusi untuk satu operator terhubung. Namun, dalam beberapa kasus, mereka dapat memiliki struktur yang lebih kompleks. Misalnya, operator `UNION` dalam kueri SPARQL dipetakan ke operasi `Copy`. Operasi ini menduplikat binding dan meneruskan salinan menjadi dua subplan, satu untuk sisi kiri dan yang lainnya untuk sisi kanan `UNION`.

Untuk informasi lebih lanjut tentang operator, lihat [Operator `explain` SPARQL Neptune](sparql-explain-operators.md).

# Cara menggunakan `explain` SPARQL untuk menganalisis eksekusi kueri Neptune
<a name="sparql-explain-using"></a>

Fitur `explain` SPARQL adalah alat swalayan di Amazon Neptune yang membantu Anda memahami pendekatan eksekusi yang diambil oleh mesin Neptune. Untuk meminta `explain`, Anda melewatkan parameter ke permintaan HTTP atau HTTPS dalam bentuk `explain=mode`.

Nilai mode dapat menjadi salah satu dari `static`, `dynamic`, atau `details`:
+ Dalam mode *statis*, `explain` mencetak hanya struktur statis dari rencana kueri.
+ Dalam mode *dinamis*, `explain` juga mencakup aspek dinamis dari rencana kueri. Aspek-aspek ini mungkin menyertakan jumlah binding menengah mengalir melalui operator, rasio binding masuk ke binding keluar, dan total waktu yang dibutuhkan oleh operator.
+ Dalam mode *detail*, `explain` mencetak informasi yang ditampilkan di mode `dynamic` ditambah rincian tambahan seperti string kueri SPARQL aktual dan perkiraan jumlah rentang untuk pola yang mendasari operator gabungan.

Neptune mendukung penggunaan `explain` dengan semua tiga protokol akses kueri SPARQL yang tercantum dalam spesifikasi [Protokol SPARQL 1.1 W3C](https://www.w3.org/TR/sparql11-protocol/#query-operation), yaitu:

1. HTTP GET

1. HTTP POST menggunakan parameter dikodekan URL

1. HTTP POST menggunakan parameter teks

Untuk informasi tentang mesin kueri SPARQL, lihat [Memahami bagaimana mesin kueri SPARQL Neptune bekerja.](sparql-explain-engine.md).

Untuk informasi tentang jenis output yang dihasilkan dengan menerapkan `explain` SPARQL, lihat [Contoh `explain` SPARQL yang dipanggil di Neptune](sparql-explain-examples.md).

# Contoh `explain` SPARQL yang dipanggil di Neptune
<a name="sparql-explain-examples"></a>

Contoh dalam bagian ini menunjukkan berbagai jenis output Anda dapat hasilkan dengan memanggil fitur `explain` SPARQL untuk menganalisis eksekusi kueri di Amazon Neptune.

**Topics**
+ [Memahami Output Explain](#sparql-explain-example-output)
+ [Contoh output mode rincian](#sparql-explain-example-details)
+ [Contoh dari output mode statis](#sparql-explain-example-static)
+ [Berbagai cara pengkodean parameter](#sparql-explain-example-parameters)
+ [Jenis output lain selain text/plain](#sparql-explain-output-options)
+ [Contoh output `explain` SPARQL saat DFE diaktifkan](#sparql-explain-output-dfe)

## Memahami Output Explain
<a name="sparql-explain-example-output"></a>

Dalam contoh ini, Jane Doe mengenal dua orang, yaitu John Doe dan Richard Roe:

```
@prefix ex: <http://example.com> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

ex:JaneDoe foaf:knows ex:JohnDoe .
ex:JohnDoe foaf:firstName "John" .
ex:JohnDoe foaf:lastName "Doe" .
ex:JaneDoe foaf:knows ex:RichardRoe .
ex:RichardRoe foaf:firstName "Richard" .
ex:RichardRoe foaf:lastName "Roe" .
.
```

Untuk menentukan nama depan semua orang yang diketahui Jane Doe, Anda dapat menulis kueri berikut:

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/> \
       SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }" \
   -H "Accept: text/csv"
```

Kueri sederhana ini mengembalikan hal berikut ini:

```
firstName
John
Richard
```

Berikutnya, mengubah perintah `curl` untuk memangil `explain` dengan menambahkan `-d "explain=dynamic"` dan menggunakan tipe output default alih-alih `text/csv`:

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/> \
       SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }" \
   -d "explain=dynamic"
```

Kueri sekarang mengembalikan output dalam format ASCII pretty-printed (jenis konten HTTP `text/plain`), yang merupakan tipe output standar:

```
╔════╤════════╤════════╤═══════════════════╤═══════════════════════════════════════════════════════╤══════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments                                             │ Mode     │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪═══════════════════════════════════════════════════════╪══════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]                                        │ -        │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ PipelineJoin      │ pattern=distinct(ex:JaneDoe, foaf:knows, ?person)     │ -        │ 1        │ 2         │ 2.00  │ 1         ║
║    │        │        │                   │ joinType=join                                         │          │          │           │       │           ║
║    │        │        │                   │ joinProjectionVars=[?person]                          │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ PipelineJoin      │ pattern=distinct(?person, foaf:firstName, ?firstName) │ -        │ 2        │ 2         │ 1.00  │ 1         ║
║    │        │        │                   │ joinType=join                                         │          │          │           │       │           ║
║    │        │        │                   │ joinProjectionVars=[?person, ?firstName]              │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ Projection        │ vars=[?firstName]                                     │ retain   │ 2        │ 2         │ 1.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ -      │ -      │ TermResolution    │ vars=[?firstName]                                     │ id2value │ 2        │ 2         │ 1.00  │ 1         ║
╚════╧════════╧════════╧═══════════════════╧═══════════════════════════════════════════════════════╧══════════╧══════════╧═══════════╧═══════╧═══════════╝
```

Untuk rincian tentang operasi di kolom `Name` dan argumennya, lihat [Operator explain](sparql-explain-operators.md).

Hal berikut ini menjelaskan output baris demi baris:

1. Langkah pertama dalam kueri utama selalu menggunakan operator `SolutionInjection` untuk menyuntikkan solusi. Solusinya kemudian diperluas ke hasil akhir melalui proses evaluasi.

   Dalam hal ini, operator menyuntikkan apa yang disebut solusi universal `{ }`. Dengan adanya klausa `VALUES` atau `BIND`, langkah ini mungkin juga menyuntikkan binding variabel yang lebih kompleks untuk memulai.

   Kolom `Units Out` menunjukkan bahwa solusi tunggal ini mengalir keluar dari operator. Kolom `Out #1` menentukan operator tempat operator ini mengumpankan hasilnya. Dalam contoh ini, semua operator terhubung ke operator yang mengikuti dalam tabel.

1. Langkah kedua adalah `PipelineJoin`. Operator menerima sebagai input solusi universal tunggal (sepenuhnya tidak dibatasi) yang dihasilkan oleh operator sebelumnya (`Units In := 1`). Operator menggabungkannya terhadap pola triple yang didefinisikan oleh argumen `pattern`. Hal ini terkait dengan pencarian sederhana untuk pola. Dalam kasus ini, pola triple didefinisikan sebagai berikut:

   ```
   distinct( ex:JaneDoe, foaf:knows, ?person )
   ```

   Argumen `joinType := join` menunjukkan bahwa ini adalah gabungan normal (jenis lain termasuk gabungan `optional`, gabungan `existence check`, dan sebagainya).

   Argumen `distinct := true` mengatakan bahwa Anda mengekstrak hanya kecocokan khas dari database (tidak ada duplikat), dan Anda mengikat kecocokan khas ke variabel `joinProjectionVars := ?person`, dideduplikasi.

   Fakta bahwa nilai kolom `Units Out` adalah 2 menunjukkan bahwa ada dua solusi yang mengalir keluar. Secara khusus, ini adalah binding untuk variabel `?person`, mencerminkan dua orang yang ditunjukkan data yang dikenal Jane Doe:

   ```
    ?person
    -------------
    ex:JohnDoe
    ex:RichardRoe
   ```

1. Dua solusi dari tahap 2 mengalir sebagai input (`Units In := 2`) ke `PipelineJoin` yang kedua. Operator ini bergabung dengan dua solusi sebelumnya dengan pola triple berikut:

   ```
   distinct(?person, foaf:firstName, ?firstName)
   ```

   Variabel `?person` dikenal terikat baik ke `ex:JohnDoe` atau ke `ex:RichardRoe` oleh solusi masuk operator. Dengan begitu, `PipelineJoin` mengekstrak nama pertama, John dan Richard. Dua solusi keluar (Unit Out: = 2) kemudian sebagai berikut:

   ```
    ?person       | ?firstName
    ---------------------------
    ex:JohnDoe    | John
    ex:RichardRoe | Richard
   ```

1. Operator proyeksi berikutnya mengambil sebagai masukan dua solusi dari tahap 3 (`Units In := 2`) dan memproyeksikan ke variabel `?firstName`. Ini menghilangkan semua binding variabel lainnya dalam pemetaan dan melewati pada dua binding (`Units Out := 2`):

   ```
    ?firstName
    ----------
    John
    Richard
   ```

1. Untuk meningkatkan kinerja, Neptunus beroperasi jika memungkinkan pada pengidentifikasi internal yang ditetapkan untuk istilah URIs seperti dan string literal, bukan pada string itu sendiri. Operator terakhir, `TermResolution`, melakukan pemetaan dari pengidentifikasi internal ini kembali ke string istilah yang sesuai.

   Dalam evaluasi kueri biasa (non-explain), hasil dihitung oleh operator terakhir kemudian diserialisasi ke dalam format serialisasi yang diminta dan dialirkan ke klien.

## Contoh output mode rincian
<a name="sparql-explain-example-details"></a>

Misalkan Anda menjalankan kueri yang sama seperti sebelumnya di mode *detail* alih-alih mode *dinamis*:

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/> \
       SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }" \
   -d "explain=details"
```

Seperti yang ditunjukkan contoh ini, outputnya sama dengan beberapa rincian tambahan seperti string kueri di bagian atas output, dan `patternEstimate` bernilai untuk operator `PipelineJoin`:

```
Query:
PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/>
SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }

╔════╤════════╤════════╤═══════════════════╤═══════════════════════════════════════════════════════╤══════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments                                             │ Mode     │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪═══════════════════════════════════════════════════════╪══════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]                                        │ -        │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ PipelineJoin      │ pattern=distinct(ex:JaneDoe, foaf:knows, ?person)     │ -        │ 1        │ 2         │ 2.00  │ 13        ║
║    │        │        │                   │ joinType=join                                         │          │          │           │       │           ║
║    │        │        │                   │ joinProjectionVars=[?person]                          │          │          │           │       │           ║
║    │        │        │                   │ patternEstimate=2                                     │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ PipelineJoin      │ pattern=distinct(?person, foaf:firstName, ?firstName) │ -        │ 2        │ 2         │ 1.00  │ 3         ║
║    │        │        │                   │ joinType=join                                         │          │          │           │       │           ║
║    │        │        │                   │ joinProjectionVars=[?person, ?firstName]              │          │          │           │       │           ║
║    │        │        │                   │ patternEstimate=2                                     │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ Projection        │ vars=[?firstName]                                     │ retain   │ 2        │ 2         │ 1.00  │ 1         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ -      │ -      │ TermResolution    │ vars=[?firstName]                                     │ id2value │ 2        │ 2         │ 1.00  │ 7         ║
╚════╧════════╧════════╧═══════════════════╧═══════════════════════════════════════════════════════╧══════════╧══════════╧═══════════╧═══════╧═══════════╝
```

## Contoh dari output mode statis
<a name="sparql-explain-example-static"></a>

Misalkan Anda menjalankan kueri yang sama seperti sebelumnya di mode *statis* (default) alih-alih mode *detail*:

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/> \
       SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }" \
   -d "explain=static"
```

Seperti yang contoh ini tunjukkan, outputnya sama, kecuali bahwa itu menghilangkan tiga kolom terakhir:

```
╔════╤════════╤════════╤═══════════════════╤═══════════════════════════════════════════════════════╤══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments                                             │ Mode     ║
╠════╪════════╪════════╪═══════════════════╪═══════════════════════════════════════════════════════╪══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]                                        │ -        ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────╢
║ 1  │ 2      │ -      │ PipelineJoin      │ pattern=distinct(ex:JaneDoe, foaf:knows, ?person)     │ -        ║
║    │        │        │                   │ joinType=join                                         │          ║
║    │        │        │                   │ joinProjectionVars=[?person]                          │          ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────╢
║ 2  │ 3      │ -      │ PipelineJoin      │ pattern=distinct(?person, foaf:firstName, ?firstName) │ -        ║
║    │        │        │                   │ joinType=join                                         │          ║
║    │        │        │                   │ joinProjectionVars=[?person, ?firstName]              │          ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────╢
║ 3  │ 4      │ -      │ Projection        │ vars=[?firstName]                                     │ retain   ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────╢
║ 4  │ -      │ -      │ TermResolution    │ vars=[?firstName]                                     │ id2value ║
╚════╧════════╧════════╧═══════════════════╧═══════════════════════════════════════════════════════╧══════════╝
```

## Berbagai cara pengkodean parameter
<a name="sparql-explain-example-parameters"></a>

Contoh kueri berikut menggambarkan dua cara yang berbeda untuk mengkodekan parameter ketika memanggil `explain` SPARQL.

**Menggunakan pengkodean URL** - Contoh ini menggunakan pengkodean URL parameter, dan menentukan output *dinamis*:

```
curl -XGET "http(s)://your_server:your_port/sparql?query=SELECT%20*%20WHERE%20%7B%20%3Fs%20%3Fp%20%3Fo%20%7D%20LIMIT%20%31&explain=dynamic"
```

**Menentukan parameter secara langsung** — Ini sama dengan kueri sebelumnya kecuali bahwa ia melewatkan parameter melalui POST langsung:

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=SELECT * WHERE { ?s ?p ?o } LIMIT 1" \
   -d "explain=dynamic"
```

## Jenis output lain selain text/plain
<a name="sparql-explain-output-options"></a>

Contoh sebelumnya menggunakan jenis output `text/plain` default. Neptune juga dapat memformat output `explain` SPARQL dalam dua format jenis MIME lainnya, yaitu `text/csv` dan `text/html`. Anda memanggil mereka dengan menetapkan header `Accept` HTTP, yang dapat Anda lakukan menggunakan bendera `-H` di `curl`, sebagai berikut:

```
  -H "Accept: output type"
```

Berikut ini adalah beberapa contohnya:

**Output `text/csv`**  
Kueri ini memanggil output jenis MIME CSV dengan menentukan `-H "Accept: text/csv"`:

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=SELECT * WHERE { ?s ?p ?o } LIMIT 1" \
   -d "explain=dynamic" \
   -H "Accept: text/csv"
```

Format CSV, yang berguna untuk diimport ke dalam spreadsheet atau basis data, memisahkan bidang dalam setiap baris `explain` dengan titik koma (`;`), seperti ini:

```
ID;Out #1;Out #2;Name;Arguments;Mode;Units In;Units Out;Ratio;Time (ms)
0;1;-;SolutionInjection;solutions=[{}];-;0;1;0.00;0
1;2;-;PipelineJoin;pattern=distinct(?s, ?p, ?o),joinType=join,joinProjectionVars=[?s, ?p, ?o];-;1;6;6.00;1
2;3;-;Projection;vars=[?s, ?p, ?o];retain;6;6;1.00;2
3;-;-;Slice;limit=1;-;1;1;1.00;1
```

 

**Output `text/html`**  
Jika Anda menentukan `-H "Accept: text/html"`, maka `explain` menghasilkan tabel HTML:

```
<!DOCTYPE html>
<html>
  <body>
    <table border="1px">
      <thead>
        <tr>
          <th>ID</th>
          <th>Out #1</th>
          <th>Out #2</th>
          <th>Name</th>
          <th>Arguments</th>
          <th>Mode</th>
          <th>Units In</th>
          <th>Units Out</th>
          <th>Ratio</th>
          <th>Time (ms)</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>0</td>
          <td>1</td>
          <td>-</td>
          <td>SolutionInjection</td>
          <td>solutions=[{}]</td>
          <td>-</td>
          <td>0</td>
          <td>1</td>
          <td>0.00</td>
          <td>0</td>
        </tr>

        <tr>
          <td>1</td>
          <td>2</td>
          <td>-</td>
          <td>PipelineJoin</td>
          <td>pattern=distinct(?s, ?p, ?o)<br>
              joinType=join<br>
              joinProjectionVars=[?s, ?p, ?o]</td>
          <td>-</td>
          <td>1</td>
          <td>6</td>
          <td>6.00</td>
          <td>1</td>
        </tr>

        <tr>
          <td>2</td>
          <td>3</td>
          <td>-</td>
          <td>Projection</td>
          <td>vars=[?s, ?p, ?o]</td>
          <td>retain</td>
          <td>6</td>
          <td>6</td>
          <td>1.00</td>
          <td>2</td>
        </tr>

        <tr>
          <td>3</td>
          <td>-</td>
          <td>-</td>
          <td>Slice</td>
          <td>limit=1</td>
          <td>-</td>
          <td>1</td>
          <td>1</td>
          <td>1.00</td>
          <td>1</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>
```

HTML merender dalam browser seperti berikut ini:

![\[Contoh dari output HTML Explain SPARQL.\]](http://docs.aws.amazon.com/id_id/neptune/latest/userguide/images/sparql-explain-dynamic-html-output.png)


## Contoh output `explain` SPARQL saat DFE diaktifkan
<a name="sparql-explain-output-dfe"></a>

Berikut ini adalah contoh output `explain` SPARQL ketika mesin kueri alternatif DFE Neptune diaktifkan:

```
╔════╤════════╤════════╤═══════════════════╤═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments                                                                                                                                                                                                               │ Mode     │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]                                                                                                                                                                                                          │ -        │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ HashIndexBuild    │ solutionSet=solutionSet1                                                                                                                                                                                                │ -        │ 1        │ 1         │ 1.00  │ 22        ║
║    │        │        │                   │ joinVars=[]                                                                                                                                                                                                             │          │          │           │       │           ║
║    │        │        │                   │ sourceType=pipeline                                                                                                                                                                                                     │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ DFENode           │ DFE Stats=                                                                                                                                                                                                                    │ -        │ 101      │ 100       │ 0.99  │ 32        ║
║    │        │        │                   │ ====> DFE execution time (measured by DFEQueryEngine)                                                                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │ accepted [micros]=127                                                                                                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │ ready [micros]=2                                                                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │ running [micros]=5627                                                                                                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │ finished [micros]=0                                                                                                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ===> DFE execution time (measured in DFENode)                                                                                                                                                                           │          │          │           │       │           ║
║    │        │        │                   │ -> setupTime [ms]=1                                                                                                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │ -> executionTime [ms]=14                                                                                                                                                                                                │          │          │           │       │           ║
║    │        │        │                   │ -> resultReadTime [ms]=0                                                                                                                                                                                                │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ===> Static analysis statistics                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ --> 35907 micros spent in parser.                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │ --> 7643 micros spent in range count estimation                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ --> 2895 micros spent in value resolution                                                                                                                                                                               │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ --> 39974925 micros spent in optimizer loop                                                                                                                                                                             │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ DFEJoinGroupNode[ children={                                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │   DFEPatternNode[(?1, TERM[117442062], ?2, ?3) . project DISTINCT[?1, ?2] {rangeCountEstimate=100},                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │     OperatorInfoWithAlternative[                                                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │       rec=OperatorInfo[                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         type=INCREMENTAL_PIPELINE_JOIN,                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         costEstimates=OperatorCostEstimates[                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │           costEstimate=OperatorCostEstimate[in=1.0000,out=100.0000,io=0.0002,comp=0.0000,mem=0],                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │           worstCaseCostEstimate=OperatorCostEstimate[in=1.0000,out=100.0000,io=0.0002,comp=0.0000,mem=0]]],                                                                                                             │          │          │           │       │           ║
║    │        │        │                   │       alt=OperatorInfo[                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         type=INCREMENTAL_HASH_JOIN,                                                                                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │         costEstimates=OperatorCostEstimates[                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │           costEstimate=OperatorCostEstimate[in=1.0000,out=100.0000,io=0.0003,comp=0.0000,mem=3212],                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │           worstCaseCostEstimate=OperatorCostEstimate[in=1.0000,out=100.0000,io=0.0003,comp=0.0000,mem=3212]]]]],                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │   DFEPatternNode[(?1, TERM[150997262], ?4, ?5) . project DISTINCT[?1, ?4] {rangeCountEstimate=100},                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │     OperatorInfoWithAlternative[                                                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │       rec=OperatorInfo[                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         type=INCREMENTAL_HASH_JOIN,                                                                                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │         costEstimates=OperatorCostEstimates[                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │           costEstimate=OperatorCostEstimate[in=100.0000,out=100.0000,io=0.0003,comp=0.0000,mem=6400],                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │           worstCaseCostEstimate=OperatorCostEstimate[in=100.0000,out=100.0000,io=0.0003,comp=0.0000,mem=6400]]],                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │       alt=OperatorInfo[                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         type=INCREMENTAL_PIPELINE_JOIN,                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         costEstimates=OperatorCostEstimates[                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │           costEstimate=OperatorCostEstimate[in=100.0000,out=100.0000,io=0.0010,comp=0.0000,mem=0],                                                                                                                      │          │          │           │       │           ║
║    │        │        │                   │           worstCaseCostEstimate=OperatorCostEstimate[in=100.0000,out=100.0000,io=0.0010,comp=0.0000,mem=0]]]]]                                                                                                          │          │          │           │       │           ║
║    │        │        │                   │ },                                                                                                                                                                                                                      │          │          │           │       │           ║
║    │        │        │                   │ ]                                                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ===> DFE configuration:                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │ solutionChunkSize=5000                                                                                                                                                                                                  │          │          │           │       │           ║
║    │        │        │                   │ ouputQueueSize=20                                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │ numComputeCores=3                                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │ maxParallelIO=10                                                                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │ numInitialPermits=12                                                                                                                                                                                                    │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ====> DFE configuration (reported back)                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │ numComputeCores=3                                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │ maxParallelIO=2                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ numInitialPermits=12                                                                                                                                                                                                    │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ===> Statistics & operator histogram                                                                                                                                                                                    │          │          │           │       │           ║
║    │        │        │                   │ ==> Statistics                                                                                                                                                                                                          │          │          │           │       │           ║
║    │        │        │                   │ -> 3741 / 3668 micros total elapsed (incl. wait / excl. wait)                                                                                                                                                           │          │          │           │       │           ║
║    │        │        │                   │ -> 3741 / 3 millis total elapse (incl. wait / excl. wait)                                                                                                                                                               │          │          │           │       │           ║
║    │        │        │                   │ -> 3741 / 0 secs total elapsed (incl. wait / excl. wait)                                                                                                                                                                │          │          │           │       │           ║
║    │        │        │                   │ ==> Operator histogram                                                                                                                                                                                                  │          │          │           │       │           ║
║    │        │        │                   │ -> 47.66% of total time (excl. wait): pipelineScan (2 instances)                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │ -> 10.99% of total time (excl. wait): merge (1 instances)                                                                                                                                                               │          │          │           │       │           ║
║    │        │        │                   │ -> 41.17% of total time (excl. wait): symmetricHashJoin (1 instances)                                                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │ -> 0.19% of total time (excl. wait): drain (1 instances)                                                                                                                                                                │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ nodeId | out0   | out1 | opName            | args                                             | rowsIn | rowsOut | chunksIn | chunksOut | elapsed* | outWait | outBlocked | ratio    | rate* [M/s] | rate [M/s] | %     │          │          │           │       │           ║
║    │        │        │                   │ ------ | ------ | ---- | ----------------- | ------------------------------------------------ | ------ | ------- | -------- | --------- | -------- | ------- | ---------- | -------- | ----------- | ---------- | ----- │          │          │           │       │           ║
║    │        │        │                   │ node_0 | node_2 | -    | pipelineScan      | (?1, TERM[117442062], ?2, ?3) DISTINCT [?1, ?2]  | 0      | 100     | 0        | 1         | 874      | 0       | 0          | Infinity | 0.1144      | 0.1144     | 23.83 │          │          │           │       │           ║
║    │        │        │                   │ node_1 | node_2 | -    | pipelineScan      | (?1, TERM[150997262], ?4, ?5) DISTINCT [?1, ?4]  | 0      | 100     | 0        | 1         | 874      | 0       | 0          | Infinity | 0.1144      | 0.1144     | 23.83 │          │          │           │       │           ║
║    │        │        │                   │ node_2 | node_4 | -    | symmetricHashJoin |                                                  | 200    | 100     | 2        | 2         | 1510     | 73      | 0          | 0.50     | 0.0662      | 0.0632     | 41.17 │          │          │           │       │           ║
║    │        │        │                   │ node_3 | -      | -    | drain             |                                                  | 100    | 0       | 1        | 0         | 7        | 0       | 0          | 0.00     | 0.0000      | 0.0000     | 0.19  │          │          │           │       │           ║
║    │        │        │                   │ node_4 | node_3 | -    | merge             |                                                  | 100    | 100     | 2        | 1         | 403      | 0       | 0          | 1.00     | 0.2481      | 0.2481     | 10.99 │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ HashIndexJoin     │ solutionSet=solutionSet1                                                                                                                                                                                                │ -        │ 100      │ 100       │ 1.00  │ 4         ║
║    │        │        │                   │ joinType=join                                                                                                                                                                                                           │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ Distinct          │ vars=[?s, ?o, ?o1]                                                                                                                                                                                                      │ -        │ 100      │ 100       │ 1.00  │ 9         ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ 6      │ -      │ Projection        │ vars=[?s, ?o, ?o1]                                                                                                                                                                                                      │ retain   │ 100      │ 100       │ 1.00  │ 2         ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 6  │ -      │ -      │ TermResolution    │ vars=[?s, ?o, ?o1]                                                                                                                                                                                                      │ id2value │ 100      │ 100       │ 1.00  │ 11        ║
╚════╧════════╧════════╧═══════════════════╧═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════════╧══════════╧═══════════╧═══════╧═══════════╝
```

# Operator `explain` SPARQL Neptune
<a name="sparql-explain-operators"></a>

Bagian berikut menjelaskan operator dan parameter untuk fitur `explain` SPARQL yang saat ini tersedia di Amazon Neptune.

**penting**  
Fitur `explain` SPARQL sedang disempurnakan. Operator dan parameter yang didokumentasikan di sini mungkin berubah dalam versi mendatang.

**Topics**
+ [Operator `Aggregation`](#sparql-explain-operator-aggregation)
+ [Operator `ConditionalRouting`](#sparql-explain-operator-conditional-routing)
+ [Operator `Copy`](#sparql-explain-operator-copy)
+ [Operator `DFENode`](#sparql-explain-operator-dfenode)
+ [Operator `Distinct`](#sparql-explain-operator-distinct)
+ [Operator `Federation`](#sparql-explain-operator-federation)
+ [Operator `Filter`](#sparql-explain-operator-filter)
+ [Operator `HashIndexBuild`](#sparql-explain-operator-hash-index-build)
+ [Operator `HashIndexJoin`](#sparql-explain-operator-hash-index-join)
+ [Operator `MergeJoin`](#sparql-explain-operator-merge-join)
+ [Operator `NamedSubquery`](#sparql-explain-operator-named-subquery)
+ [Operator `PipelineJoin`](#sparql-explain-operator-pipeline-join)
+ [Operator `PipelineCountJoin`](#sparql-explain-operator-pipeline-count-join)
+ [Operator `PipelinedHashIndexJoin`](#sparql-explain-operator-pipeline-hash-index-join)
+ [Operator `Projection`](#sparql-explain-operator-projection)
+ [Operator `PropertyPath`](#sparql-explain-operator-property-path)
+ [Operator `TermResolution`](#sparql-explain-operator-term-resolution)
+ [Operator `Slice`](#sparql-explain-operator-slice)
+ [Operator `SolutionInjection`](#sparql-explain-operator-solution-injection)
+ [Operator `Sort`](#sparql-explain-operator-sort)
+ [Operator `VariableAlignment`](#sparql-explain-operator-variable-alignment)

## Operator `Aggregation`
<a name="sparql-explain-operator-aggregation"></a>

Melakukan satu agregasi atau lebih, menerapkan semantik dari operator agregasi SPARQL seperti `count`, `max`, `min`, `sum`, dan sebagainya.

`Aggregation` dilengkapi dengan pengelompokan opsional menggunakan klausa `groupBy`, dan kendala `having` opsional.

**Pendapat**
+ `groupBy` — (*Opsional*) Menyediakan klaus `groupBy` yang menentukan urutan ekspresi yang menurut pengelompokan solusi masuk.
+ `aggregates` — (*Wajib*) Menentukan daftar urut ekspresi agregasi.
+ `having` — (*Opsional*) Menambahkan kendala untuk menyaring grup, seperti yang disiratkan oleh klausul `having` dalam kueri SPARQL.

## Operator `ConditionalRouting`
<a name="sparql-explain-operator-conditional-routing"></a>

Merutekan solusi masuk berdasarkan kondisi tertentu. Solusi yang memenuhi kondisi diarahkan ke ID operator yang direferensikan oleh `Out #1`, sedangkan solusi yang tidak diarahkan ke operator direferensikan oleh `Out #2`.

**Pendapat**
+ `condition` — (*Wajib*) Kondisi perutean.

## Operator `Copy`
<a name="sparql-explain-operator-copy"></a>

Mendelegasikan aliran solusi sebagaimana ditentukan oleh mode tertentu.

**Mode**
+ `forward` — Meneruskan solusi untuk operator hilir yang diidentifikasi oleh `Out #1`. 
+ `duplicate` — Menduplikat solusi dan meneruskannya ke masing-masing dari dua operator yang diidentifikasi oleh `Out #1` dan `Out #2`.

`Copy` tidak memiliki argumen.

## Operator `DFENode`
<a name="sparql-explain-operator-dfenode"></a>

Operator ini merupakan abstraksi dari rencana yang dijalankan oleh mesin kueri alternatif DFE. Rencana DFE rinci diuraikan dalam argumen untuk operator ini. Argumen saat ini kelebihan beban untuk berisi statistik runtime rinci dari rencana DFE. Argumen berisi waktu yang dihabiskan dalam berbagai langkah eksekusi kueri oleh DFE.

Abstrak sintaks tree (AST) yang dioptimalkan logis untuk rencana kueri DFE dicetak dengan informasi tentang jenis operator yang dianggap saat perencanaan dan akibat terbaik dan terburuk terkait untuk menjalankan operator. AST saat ini terdiri dari jenis node berikut:
+ `DFEJoinGroupNode` — Merupakan gabungan dari satu `DFEPatternNodes` atau lebih.
+ `DFEPatternNode` - Merangkum pola mendasar menggunakan tupel yang cocok yang diproyeksikan keluar dari database yang mendasari.

Sub-bagiannya, `Statistics & Operator histogram`, berisi rincian tentang waktu eksekusi rencana `DataflowOp` dan rincian waktu CPU yang digunakan oleh masing-masing operator. Di bawah ini ada tabel yang mencetak statistik runtime rinci dari rencana yang dieksekusi oleh DFE.

**catatan**  
Karena DFE adalah fitur eksperimental yang dirilis dalam mode lab, format tepat output `explain` dapat berubah.

## Operator `Distinct`
<a name="sparql-explain-operator-distinct"></a>

Menghitung proyeksi yang berbeda pada subset dari variabel, menghilangkan duplikat. Akibatnya, jumlah solusi yang mengalir lebih besar dari atau sama dengan jumlah solusi yang mengalir keluar.

**Pendapat**
+ `vars` — (*Wajib*) Variabel tempat proyeksi `Distinct` akan diterapkan.

## Operator `Federation`
<a name="sparql-explain-operator-federation"></a>

Melewatkan kueri tertentu ke titik akhir SPARQL remote yang ditentukan.

**Pendapat**
+ `endpoint` — (*Wajib*) URL titik akhir dalam pernyataan `SERVICE` SPARQL. Ini bisa berupa string konstan, atau jika titik akhir kueri ditentukan berdasarkan variabel dalam kueri yang sama, ia dapat menjadi nama variabel.
+ `query` — (*Wajib*) String kueri yang direkonstruksi yang akan dikirim ke titik akhir remote. Mesin menambahkan prefiks default untuk kueri ini bahkan ketika klien tidak menentukan apapun.
+ `silent` — (*Wajib*) Boolean yang menunjukkan apakah kata kunci `SILENT` muncul setelah kata kunci tersebut. `SILENT` memberi tahu mesin untuk tidak menggagalkan seluruh kueri bahkan jika bagian `SERVICE` remote gagal.

## Operator `Filter`
<a name="sparql-explain-operator-filter"></a>

Menyaring solusi yang masuk. Hanya solusi yang memenuhi kondisi filter yang diteruskan ke operator hulu, dan yang lainnya dijatuhkan.

**Pendapat**
+ `condition` — (*Wajib*) Kondisi filter.

## Operator `HashIndexBuild`
<a name="sparql-explain-operator-hash-index-build"></a>

Membawa daftar binding dan melakukan spools pada mereka ke dalam indeks hash yang namanya didefinisikan oleh argumen `solutionSet`. Biasanya, operator berikutnya melakukan penggabungan terhadap set solusi ini, mengacunya dengan nama itu.

**Pendapat**
+ `solutionSet` — (*Wajib*) Nama set solusi indeks hash.
+ `sourceType` — (*Wajib*) Jenis sumber asal binding yang akan disimpan dalam indeks hash diperoleh:
  + `pipeline` — Melakukan spool pada solusi yang masuk dari operator hilir dalam alur operator ke dalam indeks hash.
  + `binding set` - Melakukan spool pada set mengikat tetap yang ditentukan oleh argumen `sourceBindingSet` ke dalam indeks hash.
+ `sourceBindingSet` — (*Opsional*) Jika nilai argumen `sourceType` adalah `binding set`, argumen ini menentukan set binding statis yang akan di-spool ke dalam indeks hash.

## Operator `HashIndexJoin`
<a name="sparql-explain-operator-hash-index-join"></a>

Menggabungkan solusi masuk terhadap set solusi indeks hash yang diidentifikasi oleh argumen `solutionSet`.

**Pendapat**
+ `solutionSet` — (*Wajib*) Nama set solusi yang akan digabungkan. Ini harus berupa indeks hash yang telah dibangun di langkah sebelumnya menggunakan operator `HashIndexBuild`.
+ `joinType` — (*Wajib*) Jenis gabungan yang akan dilakukan:
  + `join` — Gabungan normal, membutuhkan kecocokan persis antara semua variabel bersama.
  + `optional` — Sebuah gabungan `optional` yang menggunakan semantik operator `OPTIONAL` SPARQL.
  + `minus` — Sebuah operasi `minus` yang mempertahankan pemetaan yang tanpa mitra gabungan, menggunakan semanti operator `MINUS` SPARQL.
  + `existence check` — Memeriksa apakah ada mitra gabungan atau tidak, dan mengikat variabel `existenceCheckResultVar` ke hasil pemeriksaan ini.
+ `constraints` — (*Opsional*) Tambahan kendala gabungan yang dipertimbangkan selama penggabungan. Gabungan yang tidak memenuhi kendala ini dibuang.
+ `existenceCheckResultVar` — (*Opsional*) Hanya digunakan untuk gabungan di mana `joinType` sama dengan `existence check` (lihat argumen `joinType` sebelumnya).

## Operator `MergeJoin`
<a name="sparql-explain-operator-merge-join"></a>

Penggabungan yang digabung di lebih dari beberapa set solusi, seperti yang diidentifikasi oleh argumen `solutionSets`.

**Pendapat**
+ `solutionSets` — (*Wajib*) Set solusi yang akan digabungkan bersama.

## Operator `NamedSubquery`
<a name="sparql-explain-operator-named-subquery"></a>

Memicu evaluasi subkueri yang diidentifikasi oleh argumen `subQuery` dan melakukan spools pada hasil ke dalam set solusi yang ditentukan oleh argumen `solutionSet`. Solusi masuk untuk operator diteruskan ke subkueri dan kemudian ke operator berikutnya.

**Pendapat**
+ `subQuery` — (*Wajib*) Nama subkueri yang akan dievaluasi. Subkueri dirender secara eksplisit dalam output.
+ `solutionSet` — (*Wajib*) Nama set solusi tempat menyimpan hasil subkueri.

## Operator `PipelineJoin`
<a name="sparql-explain-operator-pipeline-join"></a>

Menerima output dari operator sebelumnya sebagai input dan menggabungkannya dengan pola tuple yang didefinisikan oleh argumen `pattern`.

**Pendapat**
+ `pattern`— (*Wajib*) Pola, yang mengambil bentuk subject-predicate-object, dan tupel grafik opsional yang mendasari gabungan. Jika `distinct` ditentukan untuk pola, gabungan hanya mengekstrak solusi yang khas dari variabel proyeksi yang ditentukan oleh `projectionVars`, alih-alih semua solusi yang cocok.
+ `inlineFilters` — (*Opsional*) Satu set filter yang akan diterapkan pada variabel dalam pola. Pola dievaluasi bersamaan dengan filter ini.
+ `joinType` — (*Wajib*) Jenis gabungan yang akan dilakukan:
  + `join` — Gabungan normal, membutuhkan kecocokan persis antara semua variabel bersama.
  + `optional` — Sebuah gabungan `optional` yang menggunakan semantik operator `OPTIONAL` SPARQL.
  + `minus` — Sebuah operasi `minus` yang mempertahankan pemetaan yang tanpa mitra gabungan, menggunakan semanti operator `MINUS` SPARQL.
  + `existence check` — Memeriksa apakah ada mitra gabungan atau tidak, dan mengikat variabel `existenceCheckResultVar` ke hasil pemeriksaan ini.
+ `constraints` — (*Opsional*) Tambahan kendala gabungan yang dipertimbangkan selama penggabungan. Gabungan yang tidak memenuhi kendala ini dibuang.
+ `projectionVars`— (*Opsional*) Variabel proyeksi. Digunakan dalam kombinasi bersama `distinct := true` untuk menegakkan ekstraksi proyeksi khas pada satu set variabel tertentu.
+ `cutoffLimit` — (*Opsional*) Batas cutoff untuk jumlah mitra gabungan yang diekstrak. Meskipun tidak ada batas secara default, Anda dapat mengatur ini ke 1 ketika melakukan gabungan untuk menerapkan klausa `FILTER (NOT) EXISTS`, di mana itu cukup untuk membuktikan atau membantah bahwa ada mitra gabungan.

## Operator `PipelineCountJoin`
<a name="sparql-explain-operator-pipeline-count-join"></a>

Varian dari `PipelineJoin`. Alih-alih bergabung, operator ini hanya menghitung mitra gabungan yang cocok dan mengikat hitungan ke variabel yang ditentukan oleh argumen `countVar`.

**Pendapat**
+ `countVar` — (*Wajib*) Variabel yang akan diikatkan pada hasil hitungan, yaitu jumlah mitra gabungan,.
+ `pattern`— (*Wajib*) Pola, yang mengambil bentuk subject-predicate-object, dan tupel grafik opsional yang mendasari gabungan. Jika `distinct` ditentukan untuk pola, gabungan hanya mengekstrak solusi yang khas dari variabel proyeksi yang ditentukan oleh `projectionVars`, alih-alih semua solusi yang cocok.
+ `inlineFilters` — (*Opsional*) Satu set filter yang akan diterapkan pada variabel dalam pola. Pola dievaluasi bersamaan dengan filter ini.
+ `joinType` — (*Wajib*) Jenis gabungan yang akan dilakukan:
  + `join` — Gabungan normal, membutuhkan kecocokan persis antara semua variabel bersama.
  + `optional` — Sebuah gabungan `optional` yang menggunakan semantik operator `OPTIONAL` SPARQL.
  + `minus` — Sebuah operasi `minus` yang mempertahankan pemetaan yang tanpa mitra gabungan, menggunakan semanti operator `MINUS` SPARQL.
  + `existence check` — Memeriksa apakah ada mitra gabungan atau tidak, dan mengikat variabel `existenceCheckResultVar` ke hasil pemeriksaan ini.
+ `constraints` — (*Opsional*) Tambahan kendala gabungan yang dipertimbangkan selama penggabungan. Gabungan yang tidak memenuhi kendala ini dibuang.
+ `projectionVars`— (*Opsional*) Variabel proyeksi. Digunakan dalam kombinasi bersama `distinct := true` untuk menegakkan ekstraksi proyeksi khas pada satu set variabel tertentu.
+ `cutoffLimit` — (*Opsional*) Batas cutoff untuk jumlah mitra gabungan yang diekstrak. Meskipun tidak ada batas secara default, Anda dapat mengatur ini ke 1 ketika melakukan gabungan untuk menerapkan klausa `FILTER (NOT) EXISTS`, di mana itu cukup untuk membuktikan atau membantah bahwa ada mitra gabungan.

## Operator `PipelinedHashIndexJoin`
<a name="sparql-explain-operator-pipeline-hash-index-join"></a>

Ini adalah indeks hash all-in-one build dan operator gabungan. Dibutuhkan daftar binding, menggulungnya menjadi indeks hash, dan kemudian bergabung dengan solusi yang masuk terhadap indeks hash.

**Pendapat**
+ `sourceType`— (*Wajib*) Jenis sumber dari mana binding untuk menyimpan dalam indeks hash diperoleh, salah satu dari:
  + `pipeline`— Penyebab `PipelinedHashIndexJoin` untuk menggeser solusi yang masuk dari operator hilir di pipa operator ke indeks hash.
  + `binding set`— Penyebab `PipelinedHashIndexJoin` untuk menggeser set pengikatan tetap yang ditentukan oleh `sourceBindingSet` argumen ke dalam indeks hash.
+ `sourceSubQuery `— (*Opsional*) Jika nilai `sourceType` argumen adalah`pipeline`, argumen ini menentukan subquery yang dievaluasi dan spooled ke dalam indeks hash.
+ `sourceBindingSet `— (*Opsional*) Jika nilai `sourceType` argumen adalah`binding set`, argumen ini menentukan set pengikatan statis yang akan di-spooled ke indeks hash.
+ `joinType`— (*Wajib*) Jenis bergabung yang akan dilakukan:
  + `join` — Gabungan normal, membutuhkan kecocokan persis antara semua variabel bersama.
  + `optional` — Sebuah gabungan `optional` yang menggunakan semantik operator `OPTIONAL` SPARQL.
  + `minus` — Sebuah operasi `minus` yang mempertahankan pemetaan yang tanpa mitra gabungan, menggunakan semanti operator `MINUS` SPARQL.
  + `existence check` — Memeriksa apakah ada mitra gabungan atau tidak, dan mengikat variabel `existenceCheckResultVar` ke hasil pemeriksaan ini.
+ `existenceCheckResultVar`— (*Opsional*) Hanya digunakan untuk bergabung di mana `joinType` sama `existence check` (lihat argumen JoinType di atas).

## Operator `Projection`
<a name="sparql-explain-operator-projection"></a>

Memproyeksikan di atas subset variabel. Jumlah solusi yang mengalir masuk sama dengan jumlah solusi yang mengalir keluar, namun bentuk solusinya berbeda, tergantung pengaturan mode.

**Mode**
+ `retain` — Menyimpan dalam solusi hanya variabel yang ditentukan oleh argumen `vars`.
+ `drop` — Jatuhkan semua variabel yang ditentukan oleh argumen `vars`.

**Pendapat**
+ `vars`— (*Wajib*) Variabel yang akan dipertahankan atau dijatuhkan, tergantung pengaturan mode.

## Operator `PropertyPath`
<a name="sparql-explain-operator-property-path"></a>

Memungkinkan jalur properti rekursif seperti `+` atau `*`. Neptune mengimplementasikan pendekatan iterasi titik tetap berdasarkan template yang ditentukan oleh argumen `iterationTemplate`. Variabel sisi kiri atau kanan yang dikenal terikat dalam template untuk setiap iterasi titik tetap, sampai tidak ada lagi solusi baru yang dapat ditemukan.

**Pendapat**
+ `iterationTemplate`— (*Wajib*) Nama dari template subkueri yang digunakan untuk mengimplementasikan iterasi titik tetap.
+ `leftTerm`— (*Wajib*) Istilah (variabel atau konstan) di sisi kiri jalur properti.
+ `rightTerm`— (*Wajib*) Istilah (variabel atau konstan) di sisi kanan jalur properti.
+ `lowerBound`— (*Wajib*) Batas bawah untuk iterasi titik tetap (baik `0` untuk kueri `*`, atau `1` untuk kueri `+`).

## Operator `TermResolution`
<a name="sparql-explain-operator-term-resolution"></a>

Menerjemahkan nilai-nilai pengidentifikasi string internal kembali ke string eksternal mereka yang sesuai, atau menerjemahkan string eksternal ke nilai-nilai pengidentifikasi string internal, tergantung modenya.

**Mode**
+ `value2id`— Memetakan istilah seperti literal dan nilai ID internal yang URIs sesuai (pengkodean ke nilai internal).
+ `id2value`— Memetakan nilai ID internal ke istilah yang sesuai seperti literal dan URIs (decoding nilai internal).

**Pendapat**
+ `vars`— (*Wajib*) Menentukan variabel yang string atau string internal IDs harus dipetakan.

## Operator `Slice`
<a name="sparql-explain-operator-slice"></a>

Mengimplementasikan potongan di atas aliran solusi masuk, menggunakan semantik klausa `LIMIT` dan `OFFSET` SPARQL.

**Pendapat**
+ `limit`— (*Opsional*) Batas pada solusi yang akan diteruskan.
+ `offset`— (*Opsional*) Offset di mana solusi dievaluasi untuk penerusan.

## Operator `SolutionInjection`
<a name="sparql-explain-operator-solution-injection"></a>

Tidak menerima input. Menyuntikkan solusi secara statis ke dalam rencana kueri dan mencatatnya dalam argumen `solutions`.

Rencana kueri selalu dimulai dengan injeksi statis ini. Jika solusi statis yang akan disuntikkan dapat berasal dari kueri itu sendiri dengan menggabungkan berbagai sumber binding statis (misalnya, dari klausa `VALUES` atau `BIND`), maka operator `SolutionInjection` menyuntikkan solusi statis turunan ini. Dalam kasus yang paling sederhana, hal ini mencerminkan binding yang tersirat oleh klausa `VALUES` luar.

Jika tidak ada solusi statis dapat diturunkan dari kueri, `SolutionInjection` menyuntikkan solusi kosong, yang disebut solusi universal, yang diperluas dan digandakan sepanjang proses evaluasi kueri.

**Pendapat**
+ `solutions`— (*Wajib*) Urutan solusi yang disuntikkan oleh operator.

## Operator `Sort`
<a name="sparql-explain-operator-sort"></a>

Mengurutkan set solusi menggunakan kondisi pengurutan tertentu.

**Pendapat**
+ `sortOrder`— (*Wajib*) Daftar variabel yang diurutkan, masing-masing berisi pengidentifikasi `ASC` (naik) atau `DESC` (turun), digunakan secara berurutan untuk mengurutkan set solusi.

## Operator `VariableAlignment`
<a name="sparql-explain-operator-variable-alignment"></a>

Memeriksa solusi satu per satu, melakukan penyelarasan pada masing-masing pada dua variabel: `sourceVar` yang ditentukan dan `targetVar` yang ditentukan.

Jika `sourceVar` dan `targetVar` dalam solusi memiliki nilai yang sama, variabel dianggap selaras dan solusi diteruskan, dengan `sourceVar` berulang diproyeksikan keluar.

Jika variabel terikat ke nilai yang berbeda, solusinya disaring seluruhnya.

**Pendapat**
+ `sourceVar`— (*Wajib*) Variabel sumber, untuk dibandingkan dengan variabel target. Jika penyelarasan berhasil dalam solusi, yang berarti bahwa dua variabel memiliki nilai yang sama, variabel sumber diproyeksikan keluar.
+ `targetVar`— (*Wajib*) Variabel target, sebagai pembanding variabel sumber. Dipertahankan bahkan ketika penyelarasan berhasil.

# Keterbatasan `explain` SPARQL di Neptune
<a name="sparql-explain-limitations"></a>

Rilis fitur `explain` dari SPARQL Neptune memiliki keterbatasan berikut.

**Neptune Saat ini Mendukung Explain Hanya dalam Kueri SPARQL SELECT**  
Untuk informasi tentang proses evaluasi untuk bentuk kueri lainnya, seperti kueri `ASK`, `CONSTRUCT`, `DESCRIBE`, dan `SPARQL UPDATE`, Anda dapat mengubah kueri-kueri ini menjadi kueri SELECT. Kemudian gunakan `explain` untuk memeriksa kueri SELECT sesuai sebagai gantinya.

Misalnya, untuk mendapatkan Informasi `explain` tentang kueri `ASK WHERE {...}`, jalankan kueri `SELECT WHERE {...} LIMIT 1` yang sesuai bersama `explain`.

Demikian pula, untuk kueri `CONSTRUCT {...} WHERE {...}`, jatuhkan bagian `CONSTRUCT {...}` dan jalankan kueri `SELECT` dengan `explain` pada klausa `WHERE {...}` kedua. Mengevaluasi klausa `WHERE` kedua umumnya mengungkapkan tantangan utama memproses kueri `CONSTRUCT`, karena solusi yang mengalir keluar dari `WHERE` kedua ke dalam template `CONSTRUCT` umumnya hanya membutuhkan substitusi langsung.

**Operator Explain Dapat Berubah di Rilis yang Akan Datang**  
Operator `explain` SPARQL dan parameternya dapat berubah dalam rilis yang akan datang.

**Output Explain Dapat Berubah di Rilis yang Akan Datang**  
Misalnya, header kolom bisa berubah, dan lebih banyak kolom mungkin ditambahkan ke tabel.

# Kueri gabungan SPARQL di Neptune menggunakan ekstensi `SERVICE`
<a name="sparql-service"></a>

Amazon Neptune sepenuhnya mendukung ekstensi kueri gabungan SPARQL yang menggunakan kata kunci `SERVICE`. (Untuk informasi selengkapnya, lihat [Kueri Gabungan SPARQL 1.1](https://www.w3.org/TR/sparql11-federated-query/).)

Kata kunci `SERVICE` menginstruksikan mesin kueri SPARQL untuk mengeksekusi sebagian dari kueri terhadap titik akhir SPARQL jauh dan menyusun hasil kueri akhir. Hanya operasi `READ` yang dimungkinkan. Operasi `WRITE` dan `DELETE` tidak didukung. Neptune hanya dapat menjalankan kueri gabungan terhadap titik akhir SPARQL yang dapat diakses dalam cloud privat virtual (VPC). Namun, Anda juga dapat menggunakan reverse proxy di VPC untuk membuat sumber data eksternal dapat diakses dalam VPC.

**catatan**  
Saat `SERVICE` SPARQL digunakan untuk melakukan federasi pada kueri untuk dua klaster Neptune atau lebih di VPC yang sama, grup keamanan harus dikonfigurasi untuk memungkinkan semua klaster Neptune untuk berbicara satu sama lain.

**penting**  
SPARQL 1.1 Federation membuat permintaan layanan atas nama Anda saat melewatkan kueri dan parameter ke titik akhir SPARQL eksternal. Anda bertanggung jawab untuk memverifikasi bahwa titik akhir SPARQL eksternal memenuhi persyaratan penanganan data dan keamanan aplikasi Anda.

## Contoh dari kueri gabungan Neptune
<a name="sparql-service-example-1"></a>

Contoh sederhana berikut menunjukkan bagaimana kueri gabungan SPARQL bekerja.

Misalkan pelanggan mengirimkan kueri berikut ke *Neptune-1* di `http://neptune-1:8182/sparql`.

```
SELECT * WHERE {
   ?person rdf:type foaf:Person .
   SERVICE <http://neptune-2:8182/sparql> {
       ?person foaf:knows ?friend .
    }
}
```

1. *Neptune-1* mengevaluasi pola kueri pertama (*Q-1*) yang merupakan `?person rdf:type foaf:Person`, menggunakan hasilnya untuk menyelesaikan `?person` di *Q-2* (`?person foaf:knows ?friend`), dan meneruskan pola yang dihasilkan ke *Neptune-2* di `http://neptune-2:8182/sparql`.

1. *Neptune-2* mengevaluasi *Q-2* dan mengirimkan hasilnya kembali ke *Neptune-1*.

1. *Neptune-1* menggabungkan solusi untuk kedua pola dan mengirimkan hasilnya kembali ke pelanggan.

Alur ini ditunjukkan dalam diagram berikut.

![\[Diagram alur menunjukkan pola kueri gabungan SPARQL sedang dievaluasi dan respons dikirim kembali ke klien.\]](http://docs.aws.amazon.com/id_id/neptune/latest/userguide/images/federated.png)


**catatan**  
“Secara default, optimizer menentukan pada titik apa dalam eksekusi kueri bahwa instruksi `SERVICE` dijalankan. Anda dapat mengganti penempatan ini menggunakan petunjuk kueri [JoinOrder](sparql-query-hints-joinOrder.md).

## Kontrol akses untuk kueri gabungan di Neptune
<a name="sparql-service-auth"></a>

Neptunus AWS Identity and Access Management menggunakan (IAM) untuk otentikasi dan otorisasi. Kontrol akses untuk kueri gabungan dapat melibatkan lebih dari satu instans DB Neptune. Instans ini mungkin memiliki persyaratan yang berbeda untuk kontrol akses. Dalam keadaan tertentu, ini dapat membatasi kemampuan Anda untuk membuat kueri gabungan.

Pertimbangkan contoh sederhana yang disajikan di bagian sebelumnya. *Neptune-1* memanggil *Neptune-2* dengan kredensial yang sama yang memanggilnya.
+ Jika *Neptune-1* memerlukan autentikasi dan otorisasi IAM, namun tidak untuk *Neptune-2*, yang Anda butuhkan hanya izin IAM yang sesuai untuk *Neptune-1* untuk membuat kueri gabungan.
+ Jika *Neptune-1* dan *Neptune-2* keduanya memerlukan autentikasi dan otorisasi IAM, Anda perlu melampirkan izin IAM untuk kedua database untuk membuat kueri gabungan. Kedua cluster juga harus berada di AWS akun yang sama dan di wilayah yang sama. Arsitektur kueri and/or federasi lintas wilayah lintas wilayah saat ini tidak didukung.
+ Namun, dalam kasus di mana *Neptune-1* IAM-nya tidak diaktifkan tetapi diaktifkan di *Neptune-2*, Anda tidak dapat membuat kueri gabungan. Alasannya adalah bahwa *Neptune-1* tidak dapat mengambil kredensial IAM Anda dan meneruskannya ke *Neptune-2* untuk mengotorisasi bagian kedua dari kueri.