Di MySQL, MATCH()
fungsi melakukan pencarian teks lengkap. Ia menerima daftar kolom tabel yang dipisahkan koma untuk dicari.
Tabel harus memiliki FULLTEXT
indeks sebelum Anda dapat melakukan pencarian teks lengkap terhadap mereka (meskipun kueri boolean terhadap MyISAM
indeks pencarian dapat bekerja — meskipun lambat — bahkan tanpa FULLTEXT
indeks).
Anda dapat membuat FULLTEXT
indeks saat membuat tabel (menggunakan CREATE TABLE
pernyataan), atau Anda dapat menggunakan ALTER TABLE
pernyataan atau CREATE INDEX
pernyataan jika tabel sudah ada.
Secara default, pencarian tidak peka huruf besar/kecil. Untuk melakukan pencarian peka huruf besar/kecil, gunakan susunan huruf besar/kecil atau biner untuk kolom yang diindeks.
Sintaks
Sintaks untuk MATCH()
fungsinya seperti ini:
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
Dimana col1,col2,...
adalah daftar kolom yang dipisahkan koma untuk ditelusuri, dan expr
adalah string/ekspresi input.
search_modifier
opsional argumen memungkinkan Anda untuk menentukan jenis pencarian. Nilai tersebut dapat berupa salah satu dari nilai berikut:
IN NATURAL LANGUAGE MODE
IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
IN BOOLEAN MODE
WITH QUERY EXPANSION
Mode default adalah IN NATURAL LANGUAGE MODE
.
Contoh 1 – Penggunaan Dasar
Berikut ini contoh cara menggunakan fungsi ini:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('cool');
Hasil:
+---------+--------------------+ | AlbumId | AlbumName | +---------+--------------------+ | 5 | Casualties of Cool | +---------+--------------------+
Berikut tabel lengkap yang digunakan untuk menjalankan kueri di atas:
SELECT AlbumId, AlbumName FROM Albums;
Hasil:
+---------+--------------------------+ | AlbumId | AlbumName | +---------+--------------------------+ | 1 | Powerslave | | 2 | Powerage | | 3 | Singing Down the Lane | | 4 | Ziltoid the Omniscient | | 5 | Casualties of Cool | | 6 | Epicloud | | 7 | Somewhere in Time | | 8 | Piece of Mind | | 9 | Killers | | 10 | No Prayer for the Dying | | 11 | No Sound Without Silence | | 12 | Big Swing Face | | 13 | Blue Night | | 14 | Eternity | | 15 | Scandinavia | | 16 | Long Lost Suitcase | | 17 | Praise and Blame | | 18 | Along Came Jones | | 19 | All Night Wrong | | 20 | The Sixteen Men of Tain | +---------+--------------------------+
Contoh 2 – Kesalahan:“Tidak dapat menemukan indeks FULLTEXT”
InnoDB
tabel harus memiliki FULLTEXT
indeks sebelum akan mengembalikan hasil dari pencarian teks lengkap. Jika tidak memiliki FULLTEXT
indeks, Anda mungkin akan mendapatkan kesalahan berikut:
ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list
Jika Anda mendapatkan kesalahan itu, Anda harus menambahkan FULLTEXT
indeks untuk semua kolom yang Anda coba telusuri (lihat contoh berikutnya).
Pengecualian untuk ini bisa jadi jika Anda menjalankan kueri boolean terhadap MyISAM
indeks pencarian.
Untuk lebih spesifik, dokumentasi MySQL untuk pencarian teks lengkap boolean menyatakan sebagai berikut:
InnoDB
tabel memerlukanFULLTEXT
indeks pada semua kolomMATCH()
ekspresi untuk melakukan kueri boolean. Kueri Boolean terhadapMyISAM
indeks pencarian dapat bekerja bahkan tanpaFULLTEXT
index, meskipun pencarian yang dilakukan dengan cara ini akan sangat lambat.
Contoh 3 – Menambahkan Indeks FULLTEXT ke Tabel yang Ada
Berikut ini contoh penambahan FULLTEXT
indeks ke tabel yang ada:
ALTER TABLE Albums ADD FULLTEXT(AlbumName);
Dalam hal ini, saya mengindeks konten AlbumName
kolom.
Untuk mengindeks beberapa kolom, pisahkan dengan koma (lihat contoh berikutnya).
Contoh 4 – Mencari Beberapa Kolom
Jika Anda merasa perlu mencari lebih dari satu kolom, Anda harus membuat indeks yang mencakup semua kolom yang akan dicari. Untuk melakukannya, cukup sertakan setiap kolom sebagai daftar yang dipisahkan koma.
Berikut adalah contoh di mana saya menambahkan FULLTEXT
indeks ke film
tabel (yang merupakan bagian dari database sampel Sakila).
ALTER TABLE film ADD FULLTEXT(title, description);
Dalam hal ini, saya mengindeks konten title
dan description
kolom.
Sekarang kita telah membuat FULLTEXT
indeks untuk kedua kolom, kita dapat melakukan pencarian teks lengkap terhadap mereka:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('vertigo');
Hasil:
+-------------------+-----------------------------------------------------------------------------------------------------------+ | title | description | +-------------------+-----------------------------------------------------------------------------------------------------------+ | VERTIGO NORTHWEST | A Unbelieveable Display of a Mad Scientist And a Mad Scientist who must Outgun a Mad Cow in Ancient Japan | +-------------------+-----------------------------------------------------------------------------------------------------------+
Berikut pencarian lain, di mana frasa kunci yang tepat tidak cocok, tetapi setiap kata kunci dalam frasa itu cocok:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Hasil:
+-------------+---------------------------------------------------------------------------------------------------------+ | title | description | +-------------+---------------------------------------------------------------------------------------------------------+ | IRON MOON | A Fast-Paced Documentary of a Mad Cow And a Boy who must Pursue a Dentist in A Baloon | | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | +-------------+---------------------------------------------------------------------------------------------------------+
Jika Anda hanya ingin frasa yang sama persis, beri tanda kutip ganda di sekitarnya:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Iron Maiden"');
Hasil:
Empty set (0.00 sec)
Dalam hal ini, tidak ada kolom yang berisi frasa persis seperti itu.
Contoh 5 – Mengembalikan Skor Relevansi
Setiap kali Anda menggunakan MATCH()
fungsi, setiap baris dalam tabel diberi nilai relevansi. Dengan kata lain, setiap baris mendapat skor yang menentukan seberapa relevan dengan istilah pencarian. Hasilnya kemudian diurutkan berdasarkan relevansi (relevansi tertinggi terlebih dahulu).
Nilai relevansi adalah bilangan floating-point nonnegatif. Relevansi nol berarti tidak ada kesamaan. Relevansi dihitung berdasarkan jumlah kata dalam baris (dokumen), jumlah kata unik dalam baris, jumlah total kata dalam kumpulan, dan jumlah baris yang berisi kata tertentu.
Untuk mengembalikan relevansi setiap hasil, cukup sertakan MATCH()
fungsi dalam daftar kolom Anda untuk dipilih.
Contoh:
SELECT MATCH(title, description) AGAINST('Iron Maiden') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Hasil:
+-----------+-------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +-----------+-------------+---------------------------------------------------------------------------------------------------------+ | 9 | IRON MOON | A Fast-Paced Documentary of a Mad Cow And a Boy who must Pursue a Dentist in A Baloon | | 9 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | +-----------+-------------+---------------------------------------------------------------------------------------------------------+
Dalam hal ini skor relevansi sangat tinggi untuk kedua baris.
Ini satu lagi yang relevansinya lebih rendah:
SELECT MATCH(title, description) AGAINST('Saga of a Moose') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Saga of a Moose') LIMIT 15;
Hasil:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 2.4431142807006836 | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | 2.4431142807006836 | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | 2.4431142807006836 | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | | 2.4431142807006836 | FLASH WARS | A Astounding Saga of a Moose And a Pastry Chef who must Chase a Student in The Gulf of Mexico | | 2.4431142807006836 | HAROLD FRENCH | A Stunning Saga of a Sumo Wrestler And a Student who must Outrace a Moose in The Sahara Desert | | 2.4431142807006836 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | | 2.4431142807006836 | SHANE DARKNESS | A Action-Packed Saga of a Moose And a Lumberjack who must Find a Woman in Berlin | | 2.4431142807006836 | SLEEPLESS MONSOON | A Amazing Saga of a Moose And a Pastry Chef who must Escape a Butler in Australia | | 2.4431142807006836 | WAKE JAWS | A Beautiful Saga of a Feminist And a Composer who must Challenge a Moose in Berlin | | 2.4431142807006836 | WONKA SEA | A Brilliant Saga of a Boat And a Mad Scientist who must Meet a Moose in Ancient India | | 1.2399028539657593 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | 1.2399028539657593 | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | 1.2399028539657593 | ARMY FLINTSTONES | A Boring Saga of a Database Administrator And a Womanizer who must Battle a Waitress in Nigeria | | 1.2399028539657593 | BEAR GRACELAND | A Astounding Saga of a Dog And a Boy who must Kill a Teacher in The First Manned Space Station | | 1.2399028539657593 | BERETS AGENT | A Taut Saga of a Crocodile And a Boy who must Overcome a Technical Writer in Ancient China | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Perhatikan bahwa kumpulan hasil akan jauh lebih besar jika saya tidak menggunakan LIMIT 15
untuk membatasi jumlah hasil menjadi 15.
Contoh 6 – Hanya Mengembalikan Hasil Di Atas Skor Relevansi Tertentu
Kita dapat mengambil contoh sebelumnya selangkah lebih maju dan menyaring hanya hasil-hasil dengan skor relevansi tertentu. Dalam hal ini saya menetapkan bahwa nilai relevansi harus lebih tinggi dari 2.
Namun berhati-hatilah saat melakukan ini. Seperti yang terlihat di atas, nilai relevansi bisa sangat tinggi atau sangat rendah, bergantung pada faktor seperti berapa banyak teks dalam kolom, berapa banyak baris lain yang cocok dengan istilah penelusuran, dll.
SELECT MATCH(title, description) AGAINST('Saga of a Moose') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Saga of a Moose') > 2;
Hasil:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 2.4431142807006836 | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | 2.4431142807006836 | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | 2.4431142807006836 | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | | 2.4431142807006836 | FLASH WARS | A Astounding Saga of a Moose And a Pastry Chef who must Chase a Student in The Gulf of Mexico | | 2.4431142807006836 | HAROLD FRENCH | A Stunning Saga of a Sumo Wrestler And a Student who must Outrace a Moose in The Sahara Desert | | 2.4431142807006836 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | | 2.4431142807006836 | SHANE DARKNESS | A Action-Packed Saga of a Moose And a Lumberjack who must Find a Woman in Berlin | | 2.4431142807006836 | SLEEPLESS MONSOON | A Amazing Saga of a Moose And a Pastry Chef who must Escape a Butler in Australia | | 2.4431142807006836 | WAKE JAWS | A Beautiful Saga of a Feminist And a Composer who must Challenge a Moose in Berlin | | 2.4431142807006836 | WONKA SEA | A Brilliant Saga of a Boat And a Mad Scientist who must Meet a Moose in Ancient India | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Contoh 7 – Sertakan Hasil Nol Relevansi
Berikut adalah contoh daftar nilai relevansi untuk setiap baris, meskipun nilai relevansinya nol. Kita dapat melakukan ini dengan tidak menggunakan MATCH()
fungsi di WHERE
ayat.
Dalam contoh ini, saya sebenarnya tidak menggunakan WHERE
ayat. Saya hanya menggunakan LIMIT
klausa untuk membatasi jumlah hasil.
SELECT MATCH(title, description) AGAINST('Scientist') AS Relevance, title, description FROM film LIMIT 15;
Hasil:
+-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | 1.026631474494934 | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | | 0 | ACE GOLDFINGER | A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China | | 0 | ADAPTATION HOLES | A Astounding Reflection of a Lumberjack And a Car who must Sink a Lumberjack in A Baloon Factory | | 0 | AFFAIR PREJUDICE | A Fanciful Documentary of a Frisbee And a Lumberjack who must Chase a Monkey in A Shark Tank | | 0 | AFRICAN EGG | A Fast-Paced Documentary of a Pastry Chef And a Dentist who must Pursue a Forensic Psychologist in The Gulf of Mexico | | 0 | AGENT TRUMAN | A Intrepid Panorama of a Robot And a Boy who must Escape a Sumo Wrestler in Ancient China | | 0 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | 0 | AIRPORT POLLOCK | A Epic Tale of a Moose And a Girl who must Confront a Monkey in Ancient India | | 2.053262948989868 | ALABAMA DEVIL | A Thoughtful Panorama of a Database Administrator And a Mad Scientist who must Outgun a Mad Scientist in A Jet Boat | | 0 | ALADDIN CALENDAR | A Action-Packed Tale of a Man And a Lumberjack who must Reach a Feminist in Ancient China | | 0 | ALAMO VIDEOTAPE | A Boring Epistle of a Butler And a Cat who must Fight a Pastry Chef in A MySQL Convention | | 0 | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | 0 | ALI FOREVER | A Action-Packed Drama of a Dentist And a Crocodile who must Battle a Feminist in The Canadian Rockies | | 0 | ALICE FANTASIA | A Emotional Drama of a A Shark And a Database Administrator who must Vanquish a Pioneer in Soviet Georgia | | 1.026631474494934 | ALIEN CENTER | A Brilliant Drama of a Cat And a Mad Scientist who must Battle a Feminist in A MySQL Convention | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+
Contoh 8 – Mode Boolean
MySQL memungkinkan kita untuk menjalankan pencarian teks lengkap dalam mode boolean. Untuk melakukannya, tambahkan IN BOOLEAN MODE
pengubah kueri Anda.
Mode Boolean memungkinkan Anda menggunakan operator seperti +
dan -
untuk menentukan apakah kata atau frasa tertentu harus ada atau tidak.
Dalam contoh berikut, saya mengawali setiap kata dengan tanda plus (+
) untuk menunjukkan bahwa kedua kata harus ada.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga +Moose' IN BOOLEAN MODE) LIMIT 3;
Hasil:
+------------------------+---------------------------------------------------------------------------------------------+ | title | description | +------------------------+---------------------------------------------------------------------------------------------+ | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | +------------------------+---------------------------------------------------------------------------------------------+
Pada contoh berikut, saya mengubah salah satu tanda plus menjadi tanda minus (-
). Artinya hanya baris yang mengandung kata Saga
akan dikembalikan, tetapi hanya jika mereka tidak juga mengandung Moose
:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Hasil:
+------------------+-------------------------------------------------------------------------------------------------+ | title | description | +------------------+-------------------------------------------------------------------------------------------------+ | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | ARMY FLINTSTONES | A Boring Saga of a Database Administrator And a Womanizer who must Battle a Waitress in Nigeria | +------------------+-------------------------------------------------------------------------------------------------+
Tanda minus digunakan untuk mengecualikan hasil yang seharusnya dikembalikan. Oleh karena itu, jika semua kata pencarian kami diawali dengan tanda minus, set kosong akan dikembalikan.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Hasil:
Empty set (0.00 sec)
Masih banyak lagi operator yang bisa digunakan dengan pencarian boolean, seperti ~
, <
, >
, *
, dan banyak lagi. Untuk informasi lebih rinci tentang penggunaan mode boolean, lihat dokumentasi MySQL untuk Pencarian Teks Lengkap Boolean.
Contoh 9 – Dengan Perluasan Kueri Buta
Anda dapat menggunakan WITH QUERY EXPANSION
atau IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
pengubah untuk melakukan ekspansi kueri buta. Ini dapat berguna ketika frasa pencarian sangat pendek, dan di mana hasil yang dikembalikan mungkin terlalu sempit (sehingga tidak termasuk dokumen yang berpotensi relevan).
Perluasan kueri dapat memperluas pencarian dengan mengembalikan baris yang seharusnya tidak dikembalikan. Khususnya, jika baris yang tidak cocok berisi kata-kata yang juga terdapat dalam baris yang cocok, baris yang tidak cocok tersebut dapat menjadi baris yang cocok. Dengan kata lain, baris yang tidak cocok masih dapat ditampilkan, hanya karena baris tersebut berbagi kata lain dengan baris yang cocok.
Untuk menunjukkan, inilah pencarian normal tanpa perluasan kueri:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);
Hasil:
+---------+------------+ | AlbumId | AlbumName | +---------+------------+ | 13 | Blue Night | +---------+------------+
Saya secara eksplisit menyatakan IN NATURAL LANGUAGE MODE
tapi ini adalah mode default, jadi saya juga bisa menghilangkan modifier ini jika saya mau.
Dan inilah pencarian yang sama dengan perluasan kueri:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);
Hasil:
+---------+-----------------+ | AlbumId | AlbumName | +---------+-----------------+ | 13 | Blue Night | | 19 | All Night Wrong | +---------+-----------------+
Dalam hal ini, dua hasil dikembalikan. Perhatikan bagaimana hasil kedua tidak mengandung frasa pencarian (blue
). Tapi itu memang mengandung kata Night
yang juga terjadi pada hasil pertama. Jadi kueri yang diperluas menganggapnya cukup cocok.
Nama album mungkin bukan kasus penggunaan yang sangat baik untuk mode perluasan kueri. Kasus penggunaan yang lebih baik mungkin pencarian katakanlah, database , di mana kueri yang diperluas mungkin juga menampilkan dokumen yang berisi nama seperti MySQL , Oracle , dll meskipun tidak mengandung frasa database .
Ini contoh lain. Namun, contoh ini menggunakan tanda kutip ganda untuk menentukan bahwa seluruh istilah penelusuran harus ada.
Jika kita melakukan pencarian tanpa perluasan kueri:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"') LIMIT 3;
Hasil:
+------------------+--------------------------------------------------------------------------------------------------+ | title | description | +------------------+--------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | +------------------+--------------------------------------------------------------------------------------------------+
Hanya satu hasil yang dikembalikan (itu satu-satunya hasil yang berisi seluruh frasa, persis seperti yang diketik).
Tetapi jika kita menggunakan perluasan kueri buta, inilah yang terjadi:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION) LIMIT 3;
Hasil:
+--------------------+------------------------------------------------------------------------------------------------------+ | title | description | +--------------------+------------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | | DINOSAUR SECRETARY | A Action-Packed Drama of a Feminist And a Girl who must Reach a Robot in The Canadian Rockies | | VICTORY ACADEMY | A Insightful Epistle of a Mad Scientist And a Explorer who must Challenge a Cat in The Sahara Desert | +--------------------+------------------------------------------------------------------------------------------------------+
Baris pertama sama seperti saat kami tidak menggunakan perluasan kueri. Namun, kueri kemudian berjalan dan mengembalikan baris yang hanya berisi bagian dari istilah penelusuran kami. Hasil ini dibatasi hanya tiga karena saya menggunakan LIMIT 3
. Hasil sebenarnya jauh lebih besar:
SELECT COUNT(*) FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);
Hasil:
+----------+ | COUNT(*) | +----------+ | 1000 | +----------+
Sangat mungkin bahwa banyak dari hasil tersebut sama sekali tidak relevan dengan istilah pencarian. Oleh karena itu, perluasan kueri buta biasanya berfungsi paling baik untuk istilah penelusuran yang lebih pendek.
Untuk informasi selengkapnya tentang menggunakan perluasan kueri buta, lihat dokumentasi MySQL:Penelusuran Teks Lengkap dengan Perluasan Kueri.