Ada beberapa cara untuk membuat indeks di MongoDB, dan dari MongoDB 4.2, kita bisa membuat indeks wildcard.
Indeks karakter pengganti dapat dianggap sebagai semacam filter yang secara otomatis mencocokkan bidang, sub-dokumen, atau larik apa pun dalam koleksi, lalu mengindeks kecocokan tersebut.
Ini dapat berguna jika dokumen Anda berisi data tidak terstruktur dengan bidang yang berbeda dalam hierarki yang berbeda. Dalam kasus seperti itu, tidak ada cara untuk memprediksi indeks yang seharusnya, karena Anda tidak tahu data apa yang akan ada di setiap dokumen.
Indeks wildcard dapat berguna dengan data tidak terstruktur seperti itu, karena indeks tersebut mengindeks semua nilai skalar bidang, secara otomatis berulang ke subdokumen atau larik apa pun dan mengindeks semua bidang skalar di subdokumen/array.
Contoh Koleksi
Indeks wildcard tidak untuk setiap koleksi. Anda hanya akan membuat indeks karakter pengganti pada koleksi tertentu dengan dokumen yang berisi data tidak terstruktur dengan bidang berbeda dalam hierarki berbeda.
Di bawah ini adalah contoh koleksi yang disebut pets
yang mungkin merupakan kandidat yang baik untuk indeks karakter pengganti:
{
"_id" : 1,
"name" : "Wag",
"details" : {
"type" : "Dog",
"weight" : 20,
"awards" : {
"Florida Dog Awards" : "Top Dog",
"New York Marathon" : "Fastest Dog",
"Sumo 2020" : "Biggest Dog"
}
}
}
{
"_id" : 2,
"name" : "Fetch",
"details" : {
"born" : ISODate("2020-06-22T14:00:00Z"),
"color" : "Black"
}
}
{
"_id" : 3,
"name" : "Scratch",
"details" : {
"eats" : [
"Mouse Porridge",
"Bird Soup",
"Caviar"
],
"type" : "Cat",
"born" : ISODate("2020-12-19T14:00:00Z")
}
}
Masing-masing dari 3 dokumen dalam koleksi ini memiliki details
bidang, tetapi mereka berisi bidang yang berbeda dalam bidang itu. Ini tidak konsisten. Ini biasanya akan mempersulit pembuatan indeks, karena kami tidak tahu bidang apa yang akan ada di setiap dokumen. Kami mungkin perlu membuat beberapa indeks, setelah analisis yang cermat terhadap kemungkinan struktur dokumen.
Untungnya kita bisa membuat indeks wildcard.
Tapi pertama-tama, mari kita lihat seperti apa rencana kueri saat menanyakan salah satu bidang tersebut. Bayangkan kita ingin mengetahui anjing mana yang mendapat penghargaan “Anjing Tercepat” di New York Marathon. Kita dapat melakukan hal berikut:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } )
Dan jika kita ingin memeriksa rencana kueri, kita dapat menambahkan explain()
sampai akhir:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()
Yang mengembalikan berikut ini:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "PetHotel.pets",
"indexFilterSet" : false,
"parsedQuery" : {
"details.awards.New York Marathon" : {
"$eq" : "Fastest Dog"
}
},
"queryHash" : "EC0D5185",
"planCacheKey" : "EC0D5185",
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"details.awards.New York Marathon" : {
"$eq" : "Fastest Dog"
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"ok" : 1
}
Yang memberi tahu kita bahwa ia akan melakukan pemindaian koleksi (COLLSCAN), yang berarti ia harus memindai setiap dokumen untuk mencari bidang tersebut.
Buat Indeks Wildcard
Berikut ini contoh pembuatan indeks karakter pengganti untuk koleksi di atas.
db.pets.createIndex({ "details.$**": 1 });
Keluaran:
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
Itu dia. Indeks wildcard telah dibuat.
Untuk membuat indeks wildcard kami menggunakan nama bidang yang ingin kami buat indeksnya (dalam hal ini details
bidang), lalu kami menambahkannya dengan titik (.
), dan kemudian bagian penting, $**
bagian.
$**
menentukan bahwa indeks karakter pengganti harus dibuat dari bidang ini dan semua subdokumennya.
Awalan $**
dengan details
membatasi cakupan indeks karakter pengganti hanya pada details
lapangan.
Sekarang mari kita periksa kembali rencana kueri untuk kueri yang disebutkan di atas:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()
Hasil:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "PetHotel.pets",
"indexFilterSet" : false,
"parsedQuery" : {
"details.awards.New York Marathon" : {
"$eq" : "Fastest Dog"
}
},
"queryHash" : "EC0D5185",
"planCacheKey" : "7DFA23ED",
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"$_path" : 1,
"details.awards.New York Marathon" : 1
},
"indexName" : "details.$**_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"$_path" : [ ],
"details.awards.New York Marathon" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"$_path" : [
"[\"details.awards.New York Marathon\", \"details.awards.New York Marathon\"]"
],
"details.awards.New York Marathon" : [
"[\"Fastest Dog\", \"Fastest Dog\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
"ok" : 1
}
Kali ini pemindaian koleksi (COLLSCAN) telah digantikan oleh pemindaian indeks (IXSCAN) pada indeks wildcard kami yang baru dibuat.
Setiap bidang dalam details
our kami bidang telah diindeks sebagai jalur/nilai, dan ada entri dalam indeks untuk setiap bidang dalam hierarki. Di mana nilai bidang adalah subdokumen (seperti awards
kami bidang), pengindeksan telah turun ke subdokumen dan mengulangi prosesnya.
Membuat Indeks Wildcard di Semua Jalur Bidang
Pada contoh sebelumnya, kami membuat indeks wildcard pada jalur bidang tunggal. Anda dapat membuat indeks karakter pengganti di semua jalur bidang hanya dengan menggunakan $**
tanpa mengawalinya dengan bidang.
Misalnya, kita bisa melakukan ini:
db.pets.createIndex({ "$**": 1 });
Itu akan membuat indeks karakter pengganti di semua jalur bidang.
Sebenarnya, itu tidak sepenuhnya benar. Secara default, indeks karakter pengganti tidak dibuat di _id
bidang. Untuk memasukkan _id
bidang, Anda harus memasukkannya ke dalam wildcardProjection
dokumen.
Tidak Dapat Membuat Indeks Wildcard? Periksa Setelan ini.
mongod
featureCompatibilityVersion
minimal harus 4.2
untuk membuat indeks wildcard.
Anda dapat memeriksa pengaturan ini dengan kode berikut:
db.adminCommand(
{
getParameter: 1,
featureCompatibilityVersion: 1
}
)
Anda dapat mengaturnya menggunakan setFeatureCompatibilityVersion
perintah:
db.adminCommand( { setFeatureCompatibilityVersion: "4.4" } )
setFeatureCompatibilityVersion
perintah harus dijalankan di admin
basis data.