Enjin carian Lucene: Kuat, fleksibel dan percuma

Jangan biarkan nombor versi rendah - 0.04 pada Ogos 2000 - menipu anda. Mesin pencari Lucene adalah alat carian yang kuat, kuat, dan fleksibel, siap menangani banyak masalah carian biasa. Dan kerana sekarang boleh didapati di bawah lesen sumber terbuka LGPL yang lebih fleksibel, harganya (percuma!) Juga sesuai.

Doug Cutting, pembangun alat carian teks dan pengambilan teks yang berpengalaman, mencipta Lucene. Cutting adalah pengarang utama mesin carian V-Twin (sebahagian daripada usaha sistem operasi Apple Copland) dan kini merupakan arkitek kanan di Excite. Dia merancang Lucene untuk mempermudah menambahkan kemampuan pengindeksan dan carian ke pelbagai aplikasi, termasuk:

  • E-mel yang boleh dicari: Aplikasi e-mel dapat memungkinkan pengguna mencari pesan yang diarkibkan dan menambahkan pesan baru ke indeks ketika mereka tiba.
  • Pencarian dokumentasi dalam talian: Pembaca dokumentasi - berbasis CD, berbasis Web, atau tertanam dalam aplikasi - dapat memungkinkan pengguna mencari dokumentasi dalam talian atau penerbitan yang diarkibkan.
  • Halaman Web yang Boleh Dicari: Penyemak imbas Web atau pelayan proksi dapat membina mesin carian peribadi untuk mengindeks setiap Halaman Web yang dikunjungi pengguna, yang memungkinkan pengguna untuk mengunjungi halaman dengan mudah.
  • Pencarian laman web: Program CGI dapat memungkinkan pengguna mencari di Situs Web Anda.
  • Pencarian kandungan: Aplikasi dapat memungkinkan pengguna mencari dokumen tersimpan untuk konten tertentu; ini dapat disatukan ke dalam dialog Open Document.
  • Kontrol versi dan pengurusan konten: Sistem pengurusan dokumen dapat mengindeks dokumen, atau versi dokumen, sehingga dapat diambil dengan mudah.
  • Suapan khidmat berita dan kawat: Pelayan berita atau relay dapat mengindeks artikel semasa mereka tiba.

Sudah tentu, banyak mesin pencari dapat melaksanakan kebanyakan fungsi tersebut, tetapi hanya sedikit alat carian sumber terbuka yang menawarkan kemudahan penggunaan, pelaksanaan cepat, dan fleksibilitas Lucene.

Saya pertama kali menggunakan Lucene ketika mengembangkan Eyebrowse, alat berasaskan Java sumber terbuka untuk membuat katalog dan melayari senarai surat. (Lihat Sumber untuk pautan.) Syarat utama untuk Eyebrowse adalah kemampuan carian dan pengambilan mesej yang fleksibel. Ini menuntut komponen pengindeksan dan pencarian yang akan mengemas kini pangkalan indeks dengan cekap ketika pesan baru tiba, membolehkan banyak pengguna mencari dan mengemas kini pangkalan indeks secara serentak, dan skala ke arkib yang mengandungi berjuta-juta mesej.

Setiap mesin carian sumber terbuka lain yang saya nilaikan, termasuk Swish-E, Glimpse, iSearch, dan libibex, kurang sesuai dengan keperluan Eyebrowse dalam beberapa cara. Ini akan menjadikan integrasi bermasalah dan / atau memakan masa. Dengan Lucene, saya menambahkan pengindeksan dan mencari ke Eyebrowse dalam masa lebih dari setengah hari, dari muat turun awal hingga kod yang berfungsi sepenuhnya! Ini adalah kurang dari sepersepuluh dari masa pembangunan yang saya belanjakan, dan menghasilkan hasil yang lebih bersepadu dan kaya ciri daripada alat carian lain yang saya anggap.

Bagaimana enjin carian berfungsi

Membuat dan mengekalkan indeks terbalik adalah masalah utama ketika membina mesin carian kata kunci yang cekap. Untuk mengindeks dokumen, anda mesti mengimbasnya terlebih dahulu untuk menghasilkan senarai catatan. Posting menerangkan kejadian perkataan dalam dokumen; mereka biasanya merangkumi kata, ID dokumen, dan mungkin lokasi atau kekerapan perkataan dalam dokumen.

Sekiranya anda menganggap pengeposan sebagai tupel borang , satu set dokumen akan menghasilkan senarai catatan yang disusun mengikut ID dokumen. Tetapi untuk mencari dokumen dengan berkesan yang mengandungi kata-kata tertentu, anda harus menyusun catatan mengikut perkataan (atau dengan kata dan dokumen, yang akan membuat carian berbilang kata lebih cepat). Dalam pengertian ini, membina indeks carian pada dasarnya adalah masalah penyortiran. Indeks carian adalah senarai catatan yang disusun mengikut perkataan.

Pelaksanaan yang inovatif

Sebilangan besar enjin carian menggunakan B-tree untuk mengekalkan indeks; mereka agak stabil berkenaan dengan penyisipan dan mempunyai ciri-ciri I / O yang berkelakuan baik (pencarian dan penyisipan adalah operasi O (log n)). Lucene mengambil pendekatan yang sedikit berbeza: daripada mengekalkan satu indeks, ia membina beberapa segmen indeks dan menggabungkannya secara berkala. Untuk setiap dokumen baru yang diindeks, Lucene membuat segmen indeks baru, tetapi dengan cepat menggabungkan segmen kecil dengan segmen yang lebih besar - ini menjadikan jumlah segmen kecil sehingga carian tetap cepat. Untuk mengoptimumkan indeks untuk carian pantas, Lucene dapat menggabungkan semua segmen menjadi satu, yang berguna untuk indeks yang jarang dikemas kini. Untuk mengelakkan konflik (atau mengunci overhead) antara pembaca dan penulis indeks, Lucene tidak pernah mengubah segmen di tempat, ia hanya mewujudkan yang baru. Semasa menggabungkan segmen,Lucene menulis segmen baru dan menghapus yang lama - setelah ada pembaca aktif menutupnya. Pendekatan ini berskala baik, menawarkan kepada pengembang tahap kelenturan yang tinggi dalam memperdagangkan kelajuan pengindeksan untuk mencari kecepatan, dan mempunyai ciri I / O yang diinginkan untuk penggabungan dan pencarian.

Segmen indeks Lucene terdiri daripada beberapa fail:

  • Indeks kamus yang mengandungi satu entri untuk setiap 100 entri dalam kamus
  • Kamus yang mengandungi satu entri untuk setiap perkataan unik
  • Fail pengeposan yang mengandungi entri untuk setiap catatan

Oleh kerana Lucene tidak pernah mengemas kini segmen di tempat, ia dapat disimpan dalam fail rata dan bukannya B-tree yang rumit. Untuk pengambilan cepat, indeks kamus mengandungi offset ke dalam fail kamus, dan kamus menyimpan offset ke dalam fail pengeposan. Lucene juga melaksanakan pelbagai muslihat untuk memampatkan kamus dan menyiarkan fail - dengan itu mengurangkan cakera I / O - tanpa menimbulkan overhead CPU yang besar.

Menilai enjin carian

Enjin carian sumber terbuka yang banyak digunakan termasuk Swish-E, Glimpse, libibex, freeWAIS, dan iSearch. Seperti pakej perisian, setiap perisian dioptimumkan untuk digunakan dalam situasi tertentu; selalunya sukar untuk menggunakan alat ini di luar domain yang dimaksudkan. Pertimbangkan ciri berikut semasa menilai mesin pencari:

  • Pengindeksan pertambahan berbanding kumpulan: Sebilangan enjin carian hanya menyokong pengindeksan kumpulan; setelah mereka membuat indeks untuk sekumpulan dokumen, menambahkan dokumen baru menjadi sukar tanpa mengindeks semua dokumen. Pengindeksan tambahan memungkinkan penambahan dokumen dengan mudah ke indeks yang ada. Untuk sebilangan aplikasi, seperti yang mengendalikan suapan data langsung, kenaikan indeks sangat penting. Lucene menyokong kedua-dua jenis pengindeksan.
  • Sumber data: Banyak enjin carian hanya dapat mengindeks fail atau Halaman Web. Aplikasi kelemahan ini di mana data yang diindeks berasal dari pangkalan data, atau di mana terdapat banyak dokumen maya dalam satu fail, seperti arkib ZIP. Lucene membenarkan pemaju untuk menyerahkan dokumen tersebut ke pengindeks melalui a Stringatau an InputStream, yang membolehkan sumber data diabstrak dari data. Walau bagaimanapun, dengan pendekatan ini, pembangun mesti menyediakan pembaca yang sesuai untuk data tersebut.
  • Kawalan pengindeksan: Beberapa mesin pencari dapat merangkak secara automatik melalui pohon direktori atau laman web untuk mencari dokumen yang akan diindeks. Walaupun ini mudah jika data anda sudah disimpan dengan cara ini, pengindeks berdasarkan perayap sering memberikan fleksibiliti terhad untuk aplikasi yang memerlukan pengawasan yang terperinci terhadap dokumen yang diindeks. Oleh kerana Lucene beroperasi terutamanya dalam mod tambahan, ia membolehkan aplikasi mencari dan mengambil dokumen.
  • Format fail: Beberapa mesin pencari hanya dapat mengindeks teks atau dokumen HTML; yang lain menyokong mekanisme penapis, yang menawarkan alternatif mudah untuk mengindeks dokumen pemprosesan kata, dokumen SGML, dan format fail lain. Lucene menyokong mekanisme sedemikian.
  • Penandaan kandungan: Beberapa mesin carian menganggap dokumen sebagai satu aliran token; yang lain membenarkan spesifikasi beberapa bidang data dalam dokumen, seperti "subjek," "abstrak," "pengarang," dan "badan." Ini membenarkan pertanyaan semantik yang lebih kaya seperti "pengarang mengandungi Hamilton DAN badan mengandungi Perlembagaan." Lucene menyokong penandaan kandungan dengan menganggap dokumen sebagai koleksi bidang, dan menyokong pertanyaan yang menentukan bidang mana yang hendak dicari.
  • Pemprosesan kata berhenti : Kata biasa, seperti "a," "dan," dan "the", menambah sedikit nilai pada indeks carian. Tetapi kerana kata-kata ini sangat umum, pengkatalogan mereka akan banyak menyumbang kepada masa pengindeksan dan ukuran indeks. Sebilangan besar enjin carian tidak akan mengindeks kata-kata tertentu, yang disebut kata berhenti. Ada yang menggunakan senarai kata berhenti, sementara yang lain memilih kata berhenti secara statistik. Lucene menangani kata berhenti dengan Analyzermekanisme yang lebih umum , yang akan dijelaskan kemudian, dan menyediakan StopAnalyzerkelas, yang menghilangkan kata berhenti dari aliran input.
  • Stemming: Selalunya, pengguna menginginkan pertanyaan untuk satu perkataan agar sesuai dengan perkataan lain yang serupa. Contohnya, pertanyaan untuk "lompat" mungkin juga sesuai dengan perkataan "melompat," "pelompat," atau "lompat." Mengurangkan kata ke bentuk akarnya disebut stemming . Lucene belum melaksanakan penangkapan, tetapi anda boleh menambahkan penahan dengan mudah melalui Analyzerkelas yang lebih canggih .
  • Ciri-ciri pertanyaan: Enjin carian menyokong pelbagai ciri pertanyaan. Sebilangan menyokong pertanyaan Boolean penuh; yang lain menyokong dan pertanyaan sahaja . Sebilangan mengembalikan skor "relevansi" dengan setiap hit. Ada yang dapat menangani pertanyaan yang berdekatan atau dekat - "carian diikuti oleh mesin" atau "Knicks dekat Celtics" - yang lain hanya dapat mencari pada satu kata kunci. Ada yang dapat mencari beberapa indeks sekaligus dan menggabungkan hasilnya untuk memberikan skor relevan yang bermakna. Lucene menyokong pelbagai ciri pertanyaan, termasuk semua yang disenaraikan di atas. Walau bagaimanapun, Lucene tidak menyokong pertanyaan Soundex yang berharga, atau "terdengar seperti,".
  • Serentak: Bolehkah beberapa pengguna mencari indeks pada masa yang sama? Bolehkah pengguna mencari indeks sementara yang lain mengemas kini? Lucene membolehkan pengguna mencari indeks secara urus niaga, walaupun pengguna lain mengemas kini indeks secara serentak.
  • Sokongan bukan bahasa Inggeris: Banyak enjin carian secara implisit menganggap bahawa bahasa Inggeris adalah bahasa sasaran; ini dapat dilihat dalam bidang seperti senarai kata berhenti, algoritma berpunca, dan penggunaan jarak untuk memadankan pertanyaan frasa. Oleh kerana Lucene memproses aliran input melalui Analyzerkelas yang disediakan oleh pembangun, adalah mungkin untuk melakukan penapisan khusus bahasa.

Walaupun tidak lengkap, senarai di atas menawarkan titik awal untuk menilai mesin pencari untuk projek tertentu. Beberapa alat carian kurang sesuai dengan tugas tertentu - memahami kehendak aplikasi anda dapat membantu anda memilih alat yang tepat untuk pekerjaan tersebut.

Menggunakan Lucene

Saya akan menggambarkan cara menggunakan Lucene untuk membuat, mengisi, dan mencari indeks. Untuk kejelasan, penyataan import dan pengendalian pengecualian telah dihilangkan dari contoh program. Dalam ilustrasi ini, saya telah menyimpan indeks carian di sistem fail (anda boleh menyimpan indeks di mana sahaja, misalnya, dalam memori atau dalam pangkalan data). Fail yang diindeks adalah fail teks ringkas. Dengan Lucene, anda juga dapat dengan mudah mengindeks format dokumen lain dan dokumen yang tidak disimpan dalam fail.

Buat indeks

The simple program CreateIndex.java creates an empty index by generating an IndexWriter object and instructing it to build an empty index. In this example, the name of the directory that will store the index is specified on the command line.

public class CreateIndex { // usage: CreateIndex index-directory public static void main(String[] args) throws Exception { String indexPath = args[0]; IndexWriter writer; // An index is created by opening an IndexWriter with the // create argument set to true. writer = new IndexWriter(indexPath, null, true); writer.close(); } } 

Index text documents

IndexFile.java shows how to add documents -- the files named on the command line -- to an index. For each file, IndexFiles creates a Document object, then calls IndexWriter.addDocument to add it to the index. From Lucene's point of view, a Document is a collection of fields that are name-value pairs. A Field can obtain its value from a String, for short fields, or an InputStream, for long fields. Using fields allows you to partition a document into separately searchable and indexable sections, and to associate metadata -- such as name, author, or modification date -- with a document. For example, when storing mail messages, you could put a message's subject, author, date, and body in separate fields, then build semantically richer queries like "subject contains Java AND author contains Gosling." In the code below, we store two fields in each Document: path, to identify the original file path so it can be retrieved later, and body, for the file's contents.

public class IndexFiles { // usage: IndexFiles index-path file . . . public static void main(String[] args) throws Exception { String indexPath = args[0]; IndexWriter writer; writer = new IndexWriter(indexPath, new SimpleAnalyzer(), false); for (int i=1; i