Bagikan melalui


Menentukan proyeksi indeks untuk pengindeksan induk-turunan

Untuk indeks yang berisi dokumen yang dipotong, proyeksi indeks menentukan bagaimana konten induk-turunan dipetakan ke bidang dalam indeks pencarian untuk pengindeksan satu-ke-banyak. Melalui proyeksi indeks, Anda dapat mengirim konten ke:

  • Indeks tunggal, di mana bidang induk diulang untuk setiap gugus, tetapi butir indeks berada di tingkat gugus. Tutorial RAG adalah contoh pendekatan ini.

  • Dua atau lebih indeks, di mana indeks induk memiliki bidang yang terkait dengan dokumen induk, dan indeks anak diatur di sekitar gugus. Indeks anak adalah korpus pencarian utama, tetapi indeks induk dapat digunakan untuk kueri pencarian saat Anda ingin mengambil bidang induk dari potongan tertentu, atau untuk kueri independen.

Sebagian besar implementasi adalah indeks tunggal yang diatur di sekitar gugus dengan bidang induk, seperti nama file dokumen, mengulangi untuk setiap gugus. Namun, sistem dirancang untuk mendukung indeks terpisah dan beberapa anak jika itu persyaratan Anda. Pencarian Azure AI tidak mendukung gabungan indeks sehingga kode aplikasi Anda harus menangani indeks mana yang akan digunakan.

Proyeksi indeks didefinisikan dalam set keterampilan. Ini bertanggung jawab untuk mengoordinasikan proses pengindeksan yang mengirim potongan konten ke indeks pencarian, bersama dengan konten induk yang terkait dengan setiap gugus. Ini meningkatkan cara kerja pemotongan data asli dengan memberikan lebih banyak opsi Anda untuk mengontrol bagaimana konten induk-anak diindeks.

Artikel ini menjelaskan cara membuat skema indeks dan pola proyeksi pengindeks untuk pengindeksan satu-ke-banyak.

Prasyarat

  • Alur pengindeksan berbasis pengindeksan.

  • Indeks (satu atau beberapa) yang menerima output alur pengindeks.

  • Sumber data yang didukung memiliki konten yang ingin Anda gugus. Ini bisa berupa konten vektor atau nonvektor.

  • Keterampilan yang membagi konten menjadi potongan, baik keterampilan Pemisahan Teks atau keterampilan kustom yang menyediakan fungsionalitas yang setara.

Set keterampilan berisi proyeksi pengindeks yang membentuk data untuk pengindeksan satu ke banyak. Set keterampilan juga dapat memiliki keterampilan lain, seperti keterampilan penyematan seperti AzureOpenAIEmbedding jika skenario Anda mencakup vektorisasi terintegrasi.

Dependensi pada pemrosesan pengindeks

Pengindeksan satu-ke-banyak mengambil dependensi pada set keterampilan dan pengindeksan berbasis pengindeks yang mencakup empat komponen berikut:

  • Sebuah sumber data
  • Satu atau beberapa indeks untuk konten yang dapat dicari
  • Set keterampilan yang berisi proyeksi indeks*
  • Pengindeks

Data Anda dapat berasal dari sumber data yang didukung, tetapi asumsinya adalah bahwa konten cukup besar sehingga Anda ingin memotongnya, dan alasan untuk memotongnya adalah anda menerapkan pola RAG yang menyediakan data dasar ke model obrolan. Atau, Anda menerapkan pencarian vektor dan perlu memenuhi persyaratan ukuran input yang lebih kecil dari model penyematan.

Pengindeks memuat data terindeks ke dalam indeks yang telah ditentukan sebelumnya. Bagaimana Anda menentukan skema dan apakah akan menggunakan satu atau beberapa indeks adalah keputusan pertama yang dibuat dalam skenario pengindeksan satu ke banyak. Bagian berikutnya mencakup desain indeks.

Membuat indeks untuk pengindeksan satu ke banyak

Baik Anda membuat satu indeks untuk potongan yang mengulangi nilai induk, atau indeks terpisah untuk penempatan bidang induk-anak, indeks utama yang digunakan untuk pencarian dirancang di sekitar potongan data. Ini harus memiliki bidang berikut:

  • Bidang kunci dokumen secara unik mengidentifikasi setiap dokumen. Ini harus didefinisikan sebagai jenis Edm.String dengan penganalisis keyword .

  • Bidang yang mengaitkan setiap gugus dengan induknya. Jenisnya harus berjenis Edm.String. Ini tidak boleh menjadi bidang kunci dokumen, dan harus diatur filterable ke true. Ini disebut sebagai parent_id dalam contoh dan sebagai nilai kunci yang diproyeksikan dalam artikel ini.

  • Bidang lain untuk konten, seperti teks atau bidang gugus yang di-vektorisasi.

Indeks harus ada di layanan pencarian sebelum Anda membuat set keterampilan atau menjalankan pengindeks.

Skema indeks tunggal termasuk bidang induk dan anak

Indeks tunggal yang dirancang di sekitar gugus dengan konten induk yang diulang untuk setiap gugus adalah pola yang dominan untuk skenario pencarian RAG dan vektor. Kemampuan untuk mengaitkan konten induk yang benar dengan setiap gugus diaktifkan melalui proyeksi indeks.

Skema berikut adalah contoh yang memenuhi persyaratan untuk proyeksi indeks. Dalam contoh ini, bidang induk adalah parent_id dan judul. Bidang anak adalah gugus vektor dan vektor nonvektor. chunk_id adalah ID dokumen indeks ini. Pengulangan parent_id dan judul untuk setiap gugus dalam indeks.

Anda dapat menggunakan portal Azure, REST API, atau Azure SDK untuk membuat indeks.

{
    "name": "my_consolidated_index",
    "fields": [
        {"name": "chunk_id", "type": "Edm.String", "key": true, "filterable": true, "analyzer": "keyword"},
        {"name": "parent_id", "type": "Edm.String", "filterable": true},
        {"name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "retrievable": true},
        {"name": "chunk", "type": "Edm.String","searchable": true,"retrievable": true},
        {"name": "chunk_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "hnsw"}
    ],
    "vectorSearch": {
        "algorithms": [{"name": "hsnw", "kind": "hnsw", "hnswParameters": {}}],
        "profiles": [{"name": "hsnw", "algorithm": "hnsw"}]
    }
}

Menambahkan proyeksi indeks ke set keterampilan

Proyeksi indeks didefinisikan di dalam definisi set keterampilan dan terutama didefinisikan sebagai array , selectorsdi mana setiap pemilih sesuai dengan indeks target yang berbeda pada layanan pencarian. Bagian ini dimulai dengan sintaksis dan contoh untuk konteks, diikuti dengan referensi parameter.

Pilih tab untuk berbagai sintaks API. Saat ini tidak ada dukungan portal untuk menyiapkan proyeksi, selain mengedit definisi JSON skillset. Lihat contoh REST untuk JSON.

Proyeksi indeks umumnya tersedia. Kami merekomendasikan API stabil terbaru:

Berikut adalah contoh payload untuk definisi proyeksi indeks yang mungkin Anda gunakan untuk memproyeksikan output halaman individual oleh keterampilan Pemisahan Teks sebagai dokumen mereka sendiri dalam indeks pencarian.

"indexProjections": {
    "selectors": [
        {
            "targetIndexName": "my_consolidated_index",
            "parentKeyFieldName": "parent_id",
            "sourceContext": "/document/pages/*",
            "mappings": [
                {
                    "name": "chunk",
                    "source": "/document/pages/*",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "chunk_vector",
                    "source": "/document/pages/*/chunk_vector",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "title",
                    "source": "/document/title",
                    "sourceContext": null,
                    "inputs": []
                }
            ]
        }
    ],
    "parameters": {
        "projectionMode": "skipIndexingParentDocuments"
    }
}

Referensi parameter

Parameter proyeksi indeks Definisi
selectors Parameter untuk korpus pencarian utama, biasanya yang dirancang di sekitar gugus.
projectionMode Parameter opsional yang memberikan instruksi kepada pengindeks. Satu-satunya nilai yang valid untuk parameter ini adalah skipIndexingParentDocuments, dan digunakan ketika indeks gugus adalah korpus pencarian utama dan Anda perlu menentukan apakah bidang induk diindeks sebagai dokumen pencarian tambahan dalam indeks yang dipotong. Jika Anda tidak mengatur skipIndexingParentDocuments, Anda mendapatkan dokumen pencarian tambahan dalam indeks Anda yang null untuk potongan, tetapi hanya diisi dengan bidang induk. Misalnya, jika lima dokumen berkontribusi 100 gugus ke indeks, maka jumlah dokumen dalam indeks adalah 105. Lima dokumen yang dibuat atau bidang induk memiliki null untuk bidang gugus (turunan), membuatnya sangat berbeda dari sebagian besar dokumen dalam indeks. projectionMode Sebaiknya atur ke skipIndexingParentDocument.

Pemilih memiliki parameter berikut sebagai bagian dari definisinya.

Parameter pemilih Definisi
targetIndexName Nama indeks tempat data indeks diproyeksikan. Ini adalah indeks terpotong tunggal dengan bidang induk berulang, atau indeks turunan jika Anda menggunakan indeks terpisah untuk konten induk-turunan.
parentKeyFieldName Nama bidang yang menyediakan kunci untuk dokumen induk.
sourceContext Anotasi pengayaan yang menentukan granularitas untuk memetakan data ke dalam dokumen pencarian individual. Untuk informasi selengkapnya, lihat Konteks keterampilan dan bahasa anotasi input.
mappings Array pemetaan data yang diperkaya ke bidang dalam indeks pencarian. Setiap pemetaan terdiri dari:
name: Nama bidang dalam indeks pencarian tempat data harus diindeks.
source: Jalur anotasi pengayaan tempat data harus ditarik.

Masing-masing mapping juga dapat secara rekursif menentukan data dengan opsional sourceContext dan inputs bidang, mirip dengan penyimpanan pengetahuan atau Keterampilan Pembentuk. Bergantung pada aplikasi Anda, parameter ini memungkinkan Anda membentuk data ke dalam bidang jenis Edm.ComplexType dalam indeks pencarian. Beberapa LLM tidak menerima jenis kompleks dalam hasil pencarian, sehingga LLM yang Anda gunakan menentukan apakah pemetaan jenis kompleks berguna atau tidak.

Parameter mappings ini penting. Anda harus secara eksplisit memetakan setiap bidang dalam indeks anak, kecuali untuk bidang ID seperti kunci dokumen dan ID induk.

Persyaratan ini berbeda dengan konvensi pemetaan bidang lainnya di Azure AI Search. Untuk beberapa jenis sumber data, pengindeks dapat secara implisit memetakan bidang berdasarkan nama serupa, atau karakteristik yang diketahui (misalnya, pengindeks blob menggunakan jalur penyimpanan metadata unik sebagai kunci dokumen default). Namun, untuk proyeksi pengindeks, Anda harus secara eksplisit menentukan setiap pemetaan bidang di sisi "banyak" hubungan.

Jangan membuat pemetaan bidang untuk bidang kunci induk. Melakukannya mengganggu pelacakan perubahan dan refresh data yang disinkronkan.

Menangani dokumen induk

Sekarang setelah Anda melihat beberapa pola untuk pengindeksan satu-ke-banyak, mari kita bandingkan perbedaan utama tentang setiap opsi. Proyeksi indeks secara efektif menghasilkan dokumen "turunan" untuk setiap dokumen "induk" yang berjalan melalui set keterampilan. Anda memiliki beberapa pilihan untuk menangani dokumen "induk".

  • Untuk mengirim dokumen induk dan anak ke indeks terpisah, atur targetIndexName untuk definisi pengindeks Anda ke indeks induk, dan atur targetIndexName di pemilih proyeksi indeks ke indeks anak.

  • Untuk menyimpan dokumen induk dan anak dalam indeks yang sama, atur pengindeks targetIndexName dan proyeksi targetIndexName indeks ke indeks yang sama.

  • Untuk menghindari pembuatan dokumen pencarian induk dan memastikan indeks hanya berisi dokumen anak dari butir seragam, atur targetIndexName untuk definisi pengindeks dan pemilih ke indeks yang sama, tetapi tambahkan objek tambahan parameters setelah selectors, dengan kunci diatur ke skipIndexingParentDocuments, seperti yang projectionMode ditunjukkan di sini:

    "indexProjections": {
        "selectors": [
            ...
        ],
        "parameters": {
            "projectionMode": "skipIndexingParentDocuments"
        }
    }
    

Meninjau pemetaan bidang

Pengindeks berafiliasi dengan tiga jenis pemetaan bidang yang berbeda. Sebelum Anda menjalankan pengindeks, periksa pemetaan bidang Anda dan ketahui kapan harus menggunakan setiap jenis.

Pemetaan bidang ditentukan dalam pengindeks dan digunakan untuk memetakan bidang sumber ke bidang indeks. Pemetaan bidang digunakan untuk jalur data yang mengangkat data dari sumber dan meneruskannya untuk pengindeksan, tanpa langkah pemrosesan keterampilan menengah. Biasanya, pengindeks dapat secara otomatis memetakan bidang yang memiliki nama dan jenis yang sama. Pemetaan bidang eksplisit hanya diperlukan ketika ada perbedaan. Dalam pengindeksan satu-ke-banyak dan pola yang dibahas sejauh ini, Anda mungkin tidak memerlukan pemetaan bidang.

Pemetaan bidang output didefinisikan dalam pengindeks dan digunakan untuk memetakan konten yang diperkaya yang dihasilkan oleh set keterampilan ke bidang ke dalam indeks utama. Dalam pola satu-ke-banyak yang tercakup dalam artikel ini, ini adalah indeks induk dalam solusi dua indeks. Dalam contoh yang ditunjukkan dalam artikel ini, indeks induk jarang, hanya dengan bidang judul, dan bidang tersebut tidak diisi dengan konten dari pemrosesan set keterampilan, jadi kami bukan pemetaan bidang output.

Pemetaan bidang proyeksi pengindeks digunakan untuk memetakan konten yang dihasilkan set keterampilan ke bidang dalam indeks anak. Dalam kasus di mana indeks anak juga menyertakan bidang induk (seperti dalam solusi indeks terkonsolidasi), Anda harus menyiapkan pemetaan bidang untuk setiap bidang yang memiliki konten, termasuk bidang judul tingkat induk, dengan asumsi Anda ingin judul muncul di setiap dokumen yang dipotong. Jika Anda menggunakan indeks induk dan anak terpisah, proyeksi pengindeks harus memiliki pemetaan bidang hanya untuk bidang tingkat anak.

Catatan

Pemetaan bidang output dan pemetaan bidang proyeksi pengindeks menerima simpul pohon dokumen yang diperkaya sebagai input sumber. Mengetahui cara menentukan jalur ke setiap simpul sangat penting untuk menyiapkan jalur data. Untuk mempelajari selengkapnya tentang sintaks jalur, lihat Mereferensikan jalur ke simpul yang diperkaya dan definisi set keterampilan misalnya.

Jalankan pemberi indeks

Setelah Anda membuat sumber data, indeks, dan set keterampilan, Anda siap untuk membuat dan menjalankan pengindeks. Langkah ini menempatkan alur ke dalam eksekusi.

Anda dapat mengkueri indeks pencarian setelah pemrosesan menyimpulkan untuk menguji solusi Anda.

Siklus hidup konten

Bergantung pada sumber data yang mendasar, pengindeks biasanya dapat memberikan pelacakan perubahan yang sedang berlangsung dan deteksi penghapusan. Bagian ini menjelaskan siklus hidup konten pengindeksan satu-ke-banyak karena berkaitan dengan refresh data.

Untuk sumber data yang menyediakan pelacakan perubahan dan deteksi penghapusan, proses pengindeks dapat mengambil perubahan dalam data sumber Anda. Setiap kali Anda menjalankan pengindeks dan set keterampilan, proyeksi indeks diperbarui jika set keterampilan atau data sumber yang mendasarinya telah berubah. Setiap perubahan yang diambil oleh pengindeks disebarluaskan melalui proses pengayaan ke proyeksi dalam indeks, memastikan bahwa data yang Diproyeksikan adalah representasi konten saat ini di sumber data asal. Aktivitas refresh data diambil dalam nilai kunci yang diproyeksikan untuk setiap gugus. Nilai ini akan diperbarui saat data yang mendasar berubah.

Catatan

Meskipun Anda dapat mengedit data secara manual dalam dokumen yang diproyeksikan menggunakan API pendorongan indeks, Anda harus menghindarinya. Pembaruan manual untuk indeks ditimpa pada pemanggilan alur berikutnya, dengan asumsi dokumen dalam data sumber diperbarui dan sumber data mengaktifkan pelacakan perubahan atau deteksi penghapusan.

Konten yang diperbarui

Jika Anda menambahkan konten baru ke sumber data Anda, potongan baru atau dokumen anak ditambahkan ke indeks pada pengindeks berikutnya yang dijalankan.

Jika Anda memodifikasi konten yang ada di sumber data, potongan diperbarui secara bertahap dalam indeks pencarian jika sumber data yang Anda gunakan mendukung pelacakan perubahan dan deteksi penghapusan. Untuk ujian, jika kata atau kalimat berubah dalam dokumen, potongan dalam indeks target yang berisi kata atau kalimat tersebut diperbarui pada pengindeks berikutnya yang dijalankan. Jenis pembaruan lainnya, seperti mengubah jenis bidang dan beberapa atribusi, tidak didukung untuk bidang yang ada. Untuk informasi selengkapnya tentang pembaruan yang diizinkan, lihat Mengubah skema indeks.

Beberapa sumber data seperti Azure Storage mendukung pelacakan perubahan dan penghapusan secara default, berdasarkan tanda waktu. Sumber data lain seperti OneLake, Azure SQL, atau Azure Cosmos DB harus dikonfigurasi untuk pelacakan perubahan.

Konten yang dihapus

Jika konten sumber tidak ada lagi (misalnya, jika teks disingkat agar memiliki lebih sedikit gugus), dokumen anak yang sesuai dalam indeks pencarian akan dihapus. Dokumen anak yang tersisa juga mendapatkan kuncinya diperbarui untuk menyertakan nilai hash baru, meskipun kontennya tidak berubah.

Jika dokumen induk dihapus sepenuhnya dari sumber data, dokumen anak yang sesuai hanya dihapus jika penghapusan terdeteksi oleh definisi sumber data yang dataDeletionDetectionPolicy ditentukan. Jika Anda tidak memiliki dokumen induk yang dataDeletionDetectionPolicy dikonfigurasi dan perlu dihapus dari sumber data, maka Anda harus menghapus dokumen turunan secara manual jika dokumen tersebut tidak lagi diinginkan.

Nilai kunci yang diproyeksikan

Untuk memastikan integritas data untuk konten yang diperbarui dan dihapus, refresh data dalam pengindeksan satu ke banyak bergantung pada nilai kunci yang diproyeksikan di sisi "banyak". Jika Anda menggunakan vektorisasi terintegrasi atau wizard Impor dan vektorisasi data, nilai kunci yang diproyeksikan adalah parent_id bidang di sisi indeks yang dipotong atau "banyak".

Nilai kunci yang diproyeksikan adalah pengidentifikasi unik yang dihasilkan pengindeks untuk setiap dokumen. Ini memastikan keunikan dan memungkinkan pelacakan perubahan dan penghapusan berfungsi dengan benar. Kunci ini berisi segmen berikut:

  • Hash acak untuk menjamin keunikan. Hash ini berubah jika dokumen induk diperbarui pada pengindeks berikutnya berjalan.
  • Kunci dokumen induk.
  • Jalur anotasi pengayaan yang mengidentifikasi konteks tempat dokumen tersebut dihasilkan.

Misalnya, jika Anda membagi dokumen induk dengan nilai kunci "aa1b22c33" menjadi empat halaman, dan kemudian masing-masing halaman tersebut diproyeksikan sebagai dokumennya sendiri melalui proyeksi indeks:

  • aa1b22c33
  • aa1b22c33_pages_0
  • aa1b22c33_pages_1
  • aa1b22c33_pages_2

Jika dokumen induk diperbarui dalam data sumber, mungkin menghasilkan lebih banyak halaman yang dipotong, perubahan hash acak, lebih banyak halaman ditambahkan, dan konten setiap gugus diperbarui agar sesuai dengan apa pun yang ada di dokumen sumber.

Contoh indeks induk-turunan terpisah

Bagian ini memperlihatkan contoh untuk indeks induk dan turunan terpisah. Ini adalah pola yang jarang terjadi, tetapi ada kemungkinan Anda mungkin memiliki persyaratan aplikasi yang paling baik terpenuhi menggunakan pendekatan ini. Dalam skenario ini, Anda memproyeikan konten induk-turunan ke dalam dua indeks terpisah.

Setiap skema memiliki bidang untuk butir tertentu, dengan bidang ID induk umum untuk kedua indeks untuk digunakan dalam kueri pencarian. Korpus pencarian utama adalah indeks anak, tetapi kemudian mengeluarkan kueri pencarian untuk mengambil bidang induk untuk setiap kecocokan dalam hasilnya. Pencarian Azure AI tidak mendukung gabungan pada waktu kueri, sehingga kode aplikasi atau lapisan orkestrasi Anda perlu menggabungkan atau menyusun hasil yang dapat diteruskan ke aplikasi atau proses.

Indeks induk memiliki bidang dan judul parent_id. parent_id adalah kunci dokumen. Anda tidak memerlukan konfigurasi pencarian vektor kecuali Anda ingin mem-vektorisasi bidang di tingkat dokumen induk.

{
    "name": "my-parent-index",
    "fields": [

        {"name": "parent_id", "type": "Edm.String", "filterable": true},
        {"name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "retrievable": true},
    ]
}

Indeks anak memiliki bidang yang dipotong, ditambah bidang parent_id. Jika Anda menggunakan vektorisasi terintegrasi, profil penilaian, peringkat semantik, atau penganalisis, Anda akan mengaturnya dalam indeks anak.

{
    "name": "my-child-index",
    "fields": [
        {"name": "chunk_id", "type": "Edm.String", "key": true, "filterable": true, "analyzer": "keyword"},
        {"name": "parent_id", "type": "Edm.String", "filterable": true},
         {"name": "chunk", "type": "Edm.String","searchable": true,"retrievable": true},
        {"name": "chunk_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "hnsw"}
    ],
    "vectorSearch": {
        "algorithms": [{"name": "hsnw", "kind": "hnsw", "hnswParameters": {}}],
        "profiles": [{"name": "hsnw", "algorithm": "hnsw"}]
    },
    "scoringProfiles": [],
    "semanticConfiguration": [],
    "analyzers": []
}

Berikut adalah contoh definisi proyeksi indeks yang menentukan jalur data yang harus digunakan pengindeks untuk mengindeks konten. Ini menentukan nama indeks anak dalam definisi proyeksi indeks, dan menentukan pemetaan setiap bidang tingkat anak atau gugus. Ini adalah satu-satunya tempat nama indeks anak ditentukan.

"indexProjections": {
    "selectors": [
        {
            "targetIndexName": "my-child-index",
            "parentKeyFieldName": "parent_id",
            "sourceContext": "/document/pages/*",
            "mappings": [
                {
                    "name": "chunk",
                    "source": "/document/pages/*",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "chunk_vector",
                    "source": "/document/pages/*/chunk_vector",
                    "sourceContext": null,
                    "inputs": []
                }
            ]
        }
    ]
}

Definisi pengindeks menentukan komponen alur. Dalam definisi pengindeks, nama indeks yang akan disediakan adalah indeks induk. Jika Anda memerlukan pemetaan bidang untuk bidang tingkat induk, tentukan di outputFieldMappings. Untuk pengindeksan satu-ke-banyak yang menggunakan indeks terpisah, definisi pengindeks mungkin terlihat seperti contoh berikut.

{
  "name": "my-indexer",
  "dataSourceName": "my-ds",
  "targetIndexName": "my-parent-index",
  "skillsetName" : "my-skillset"
  "parameters": { },
  "fieldMappings": (optional) Maps fields in the underlying data source to fields in an index,
  "outputFieldMappings" : (required) Maps skill outputs to fields in an index,
}

Langkah selanjutnya

Pemotongan data dan pengindeksan satu ke banyak adalah bagian dari pola RAG di Azure AI Search. Lanjutkan ke tutorial dan sampel kode berikut untuk mempelajari selengkapnya tentang hal itu.