Pembungkus Ruby yang sederhana namun kuat di sekitar RediSearch, mesin pencari di atas Redis.
Pertama, Redis dan RediSearch perlu diinstal.
Anda dapat mengunduh Redis dari https://redis.io/download, dan lihat petunjuk instalasi di sini. Alternatifnya, di macOS atau Linux Anda dapat menginstal melalui Homebrew.
Untuk menginstal RediSearch, periksa, https://oss.redislabs.com/redisearch/Quick_Start.html. Setelah RediSearch dibuat, jika Anda tidak menggunakan Docker, Anda dapat memperbarui file redis.conf agar selalu memuat modul RediSearch dengan loadmodule /path/to/redisearch.so
. (Pada macOS, file redis.conf dapat ditemukan di /usr/local/etc/redis.conf
)
Setelah Redis dan RediSearch aktif dan berjalan, tambahkan baris berikut ke Gemfile Anda:
gem 'redi_search'
Kemudian:
❯ bundle
Atau instal sendiri:
❯ gem install redi_search
dan memerlukannya:
require 'redi_search'
Setelah permata diinstal dan diperlukan, Anda harus mengonfigurasinya dengan konfigurasi Redis Anda. Jika Anda menggunakan Rails, ini harus masuk dalam penginisialisasi ( config/initializers/redi_search.rb
).
RediSearch . configure do | config |
config . redis_config = {
host : "127.0.0.1" ,
port : "6379"
}
end
RediSearch berkisar pada indeks pencarian, jadi mari kita mulai dengan mendefinisikan apa itu indeks pencarian. Menurut Swifttype:
Indeks penelusuran adalah kumpulan data terstruktur yang dirujuk oleh mesin telusur saat mencari hasil yang relevan dengan kueri tertentu. Indeks adalah bagian penting dari sistem pencarian mana pun, karena indeks harus disesuaikan dengan metode pengambilan informasi spesifik dari algoritma mesin pencari. Dengan cara ini, algoritme dan indeks saling terkait erat satu sama lain. Indeks juga dapat digunakan sebagai kata kerja (pengindeksan), merujuk pada proses pengumpulan data situs web tidak terstruktur dalam format terstruktur yang disesuaikan dengan algoritma mesin pencari.
Salah satu cara memikirkan indeks adalah dengan mempertimbangkan analogi berikut antara infrastruktur pencarian dan sistem pengarsipan kantor. Bayangkan Anda menyerahkan kepada karyawan magang setumpuk ribuan lembar kertas (dokumen) dan meminta mereka untuk mengatur lembar-lembar kertas tersebut dalam lemari arsip (indeks) untuk membantu perusahaan menemukan informasi dengan lebih efisien. Peserta magang pertama-tama harus memilah-milah kertas dan memahami semua informasi yang terkandung di dalamnya, kemudian mereka harus memutuskan sistem untuk mengaturnya di lemari arsip, lalu akhirnya mereka harus memutuskan apa itu. cara paling efektif untuk mencari dan memilih file setelah berada di lemari. Dalam contoh ini, proses pengorganisasian dan pengarsipan makalah berhubungan dengan proses pengindeksan konten situs web, dan metode pencarian di seluruh file terorganisir ini dan menemukan file yang paling relevan sesuai dengan algoritma pencarian.
Ini mendefinisikan bidang dan properti bidang tersebut dalam indeks. Skema adalah DSL sederhana. Setiap bidang dapat terdiri dari empat jenis: geografis, numerik, tag, atau teks dan dapat memiliki banyak pilihan. Contoh sederhana dari skema adalah:
RediSearch :: Schema . new do
text_field :first_name
text_field :last_name
end
Opsi yang didukung untuk setiap jenis adalah sebagai berikut:
Tanpa opsi: text_field :name
text_field :name, weight: 2
text_field :name, phonetic: 'dm:en'
text_field :name, sortable: true
sortable
, untuk membuat bidang yang pembaruannya menggunakan PARTIAL tidak akan menyebabkan pengindeksan ulang dokumen secara penuh. Jika suatu bidang memiliki no_index
dan tidak memiliki sortable
, bidang tersebut hanya akan diabaikan oleh indeks.text_field :name, no_index: true
text_feidl :name, no_stem: true
Tanpa opsi: numeric_field :price
numeric_field :id, sortable: true
sortable
, untuk membuat bidang yang pembaruannya menggunakan PARTIAL tidak akan menyebabkan pengindeksan ulang dokumen secara penuh. Jika suatu bidang memiliki no_index
dan tidak memiliki sortable
, bidang tersebut hanya akan diabaikan oleh indeks.numeric_field :id, no_index: true
Tanpa opsi: tag_field :tag
tag_field :tag, sortable: true
sortable
, untuk membuat bidang yang pembaruannya menggunakan PARTIAL tidak akan menyebabkan pengindeksan ulang dokumen secara penuh. Jika suatu bidang memiliki no_index
dan tidak memiliki sortable
, bidang tersebut hanya akan diabaikan oleh indeks.tag_field :tag, no_index: true
tag_field :tag, separator: ','
Tanpa pilihan: geo_field :place
geo_field :place, sortable: true
sortable
, untuk membuat bidang yang pembaruannya menggunakan PARTIAL tidak akan menyebabkan pengindeksan ulang dokumen secara penuh. Jika suatu bidang memiliki no_index
dan tidak memiliki sortable
, bidang tersebut hanya akan diabaikan oleh indeks.geo_field :place, no_index: true
Document
adalah representasi Ruby dari hash Redis.
Anda dapat mengambil Document
menggunakan metode kelas .get
.
get(index, document_id)
mengambil satu Document
dalam Index
untuk document_id
tertentu. Anda juga dapat membuat instance Document
menggunakan metode kelas .for_object(index, record, only: [])
. Dibutuhkan instance Index
dan objek Ruby. Objek tersebut harus merespon semua field yang ditentukan dalam Schema
Index
. only
menerima array bidang dari skema dan membatasi bidang yang diteruskan ke Document
.
Setelah Anda memiliki sebuah instance Document
, ia merespons semua bidang yang ditentukan dalam Schema
Index
sebagai metode dan document_id
. document_id
secara otomatis diawali dengan nama Index
kecuali jika sudah ada untuk memastikan keunikan. Kami menambahkan nama Index
karena jika Anda memiliki dua Document
dengan id yang sama di Index
yang berbeda, kami tidak ingin Document
tersebut saling menimpa. Ada juga metode #document_id_without_index
yang menghapus nama indeks yang diawali.
Terakhir ada metode #del
yang akan menghapus Document
dari Index
.
Untuk menginisialisasi Index
, berikan nama Index
sebagai string atau simbol dan blok Schema
.
RediSearch :: Index . new ( name_of_index ) do
text_field :foobar
end
create
false
jika indeks sudah ada. Menerima beberapa opsi:max_text_fields: #{true || false}
add_field
.no_offsets: #{true || false}
no_highlight
.temporary: #{seconds}
seconds
detik tidak ada aktivitas. Timer idle internal disetel ulang setiap kali indeks dicari atau ditambahkan. Karena indeks tersebut ringan, Anda dapat membuat ribuan indeks tersebut tanpa implikasi kinerja negatif.no_highlight: #{true || false}
no_highlight
juga tersirat oleh no_offsets
.no_fields: #{true || false}
no_frequencies: #{true || false}
drop(keep_docs: false)
Index
dari instance Redis, mengembalikan boolean. Memiliki metode bang yang menyertainya yang akan memunculkan pengecualian jika terjadi kegagalan. Akan mengembalikan false
jika Index
sudah turun. Mengambil kata kunci opsi arg, keep_docs
, yang secara default akan menghapus semua hash dokumen di Redis.exist?
Index
.info
Index
.fields
Index
.add(document)
Document
. Memiliki metode bang yang menyertainya yang akan memunculkan pengecualian jika terjadi kegagalan.add_multiple(documents)
Document
. Ini memberikan cara yang lebih baik untuk menambahkan banyak dokumen ke Index
. Menerima opsi yang sama seperti add
.del(document)
Document
dari Index
.document_count
Document
dalam Index
add_field(name, type, **options, &block)
Index
.index.add_field(:first_name, :text, phonetic: "dm:en")
reindex(documents, recreate: false)
recreate
true
Index
akan dihapus dan dibuat ulang Pencarian dimulai dari instance RediSearch::Index
dengan klausa yang dapat dirangkai bersama. Saat mencari, array Document
dikembalikan yang memiliki metode pembaca publik untuk semua bidang skema.
main ❯ index = RediSearch :: Index . new ( "user_idx" ) { text_field :name , phonetic : "dm:en" }
main ❯ index . add RediSearch :: Document . for_object ( index , User . new ( "10039" , "Gene" , "Volkman" ) )
main ❯ index . add RediSearch :: Document . for_object ( index , User . new ( "9998" , "Jeannie" , "Ledner" ) )
main ❯ index . search ( "john" )
RediSearch ( 1.1 ms ) FT . SEARCH user_idx `john`
=> [ #<RediSearch::Document:0x00007f862e241b78 first: "Gene", last: "Volkman", document_id: "10039">,
#<RediSearch::Document:0x00007f862e2417b8 first: "Jeannie", last: "Ledner", document_id: "9998">]
Permintaan frasa sederhana - hello AND world
index . search ( "hello" ) . and ( "world" )
Permintaan frasa yang tepat - hello FOLLOWED BY world
index . search ( "hello world" )
Permintaan gabungan - hello OR world
index . search ( "hello" ) . or ( "world" )
Permintaan negasi - hello AND NOT world
index . search ( "hello" ) . and . not ( "world" )
Persimpangan dan persatuan yang kompleks:
# Intersection of unions
index . search ( index . search ( "hello" ) . or ( "halo" ) ) . and ( index . search ( "world" ) . or ( "werld" ) )
# Negation of union
index . search ( "hello" ) . and . not ( index . search ( "world" ) . or ( "werld" ) )
# Union inside phrase
index . search ( "hello" ) . and ( index . search ( "world" ) . or ( "werld" ) )
Semua persyaratan mendukung beberapa opsi yang dapat diterapkan.
Istilah awalan : cocok dengan semua istilah yang dimulai dengan awalan. (Mirip dengan like term%
dalam SQL)
index . search ( "hel" , prefix : true )
index . search ( "hello worl" , prefix : true )
index . search ( "hel" , prefix : true ) . and ( "worl" , prefix : true )
index . search ( "hello" ) . and . not ( "worl" , prefix : true )
Persyaratan opsional : dokumen yang berisi persyaratan opsional akan berperingkat lebih tinggi dibandingkan dokumen yang tidak mengandung persyaratan opsional
index . search ( "foo" ) . and ( "bar" , optional : true ) . and ( "baz" , optional : true )
Istilah fuzzy : pertandingan dilakukan berdasarkan jarak Levenshtein (LD). Jarak Levenshtein maksimum yang didukung adalah 3.
index . search ( "zuchini" , fuzziness : 1 )
Istilah pencarian juga dapat dicakup ke bidang tertentu menggunakan klausa where
:
# Simple field specific query
index . search . where ( name : "john" )
# Using where with options
index . search . where ( first : "jon" , fuzziness : 1 )
# Using where with more complex query
index . search . where ( first : index . search ( "bill" ) . or ( "bob" ) )
Pencarian bidang numerik memerlukan rentang:
index . search . where ( number : 0 .. 100 )
# Searching to infinity
index . search . where ( number : 0 .. Float :: INFINITY )
index . search . where ( number : - Float :: INFINITY .. 0 )
slop(level)
in_order
slop
. Kami memastikan istilah kueri muncul dalam urutan yang sama di Document
seperti di kueri, terlepas dari offset di antara istilah tersebut.no_content
Document
dan bukan kontennya. Ini berguna jika RediSearch digunakan pada model Rails yang atribut Document
tidak penting dan diubah menjadi objek ActiveRecord
.language(language)
Document
s dalam bahasa Mandarin, ini harus disetel ke bahasa Mandarin agar dapat memberi token pada istilah kueri dengan benar. Jika bahasa yang tidak didukung dikirimkan, perintah akan mengembalikan kesalahan.sort_by(field, order: :asc)
:asc
atau :desc
limit(num, offset = 0)
num
yang ditentukan pada offset
. Batas default diatur ke 10
.count
Document
yang ditemukan dalam permintaan pencarianhighlight(fields: [], opening_tag: "<b>", closing_tag: "</b>")
fields
adalah serangkaian bidang yang akan disorot.verbatim
no_stop_words
with_scores
Document
. Ini dapat digunakan untuk menggabungkan hasil dari beberapa contoh. Ini akan menambahkan metode score
ke instance Document
yang dikembalikan.return(*fields)
Document
yang dikembalikan.explain
Pemeriksaan ejaan dimulai dari instance RediSearch::Index
dan memberikan saran untuk istilah pencarian yang salah eja. Dibutuhkan argumen distance
opsional yang merupakan jarak Levenshtein maksimal untuk saran ejaan. Ia mengembalikan sebuah array di mana setiap elemen berisi saran untuk setiap istilah pencarian dan skor yang dinormalisasi berdasarkan kemunculannya dalam indeks.
main ❯ index = RediSearch :: Index . new ( "user_idx" ) { text_field :name , phonetic : "dm:en" }
main ❯ index . spellcheck ( "jimy" )
RediSearch ( 1.1 ms ) FT . SPELLCHECK user_idx jimy DISTANCE 1
=> [ #<RediSearch::Spellcheck::Result:0x00007f805591c670
term : "jimy" ,
suggestions :
[ #<struct RediSearch::Spellcheck::Suggestion score=0.0006849315068493151, suggestion="jimmy">,
#<struct RediSearch::Spellcheck::Suggestion score=0.00019569471624266145, suggestion="jim">]>]
main ❯ index . spellcheck ( "jimy" , distance : 2 ) . first . suggestions
RediSearch ( 0.5 ms ) FT . SPELLCHECK user_idx jimy DISTANCE 2
=> [ #<struct RediSearch::Spellcheck::Suggestion score=0.0006849315068493151, suggestion="jimmy">,
#<struct RediSearch::Spellcheck::Suggestion score=0.00019569471624266145, suggestion="jim">]
Integrasi dengan Rails sangat mudah! Panggil redi_search
dengan argumen kata kunci schema
dari dalam model Anda. Mantan:
class User < ApplicationRecord
redi_search do
text_field :first , phonetic : "dm:en"
text_field :last , phonetic : "dm:en"
end
end
Ini secara otomatis akan menambahkan metode User.search
dan User.spellcheck
yang berperilaku sama seperti jika Anda memanggilnya pada instance Index
.
User.reindex(recreate: false, only: [])
juga ditambahkan dan berperilaku serupa dengan RediSearch::Index#reindex
. Beberapa perbedaannya antara lain:
Document
tidak perlu diteruskan sebagai parameter pertama. Cakupan search_import
dipanggil secara otomatis dan semua catatan dikonversi ke Document
s.only
di mana Anda dapat menentukan sejumlah bidang yang akan diperbarui. Berguna jika Anda mengubah skema dan hanya perlu mengindeks bidang tertentu. Saat mendefinisikan skema, Anda dapat meneruskannya satu blok secara opsional. Jika tidak ada blok yang dilewati, name
model akan dipanggil untuk mendapatkan nilainya. Jika sebuah blok dilewatkan, nilai untuk bidang tersebut diperoleh melalui pemanggilan blok tersebut.
class User < ApplicationRecord
redi_search do
text_field :name do
" #{ first_name } #{ last_name } "
end
end
end
Anda dapat mengganti cakupan search_import
pada model untuk menarik hubungan pemuatan saat pengindeksan atau dapat digunakan untuk membatasi catatan ke indeks.
class User < ApplicationRecord
scope :search_import , -> { includes ( :posts ) }
end
Saat mencari, secara default kumpulan Document
dikembalikan. Memanggil #results
pada permintaan pencarian akan menjalankan pencarian, dan kemudian mencari semua catatan yang ditemukan dalam database dan mengembalikan relasi ActiveRecord.
Nama Index
default untuk model Index
s adalah #{model_name.plural}_#{RediSearch.env}
. Metode redi_search
mengambil argumen opsional index_prefix
yang ditambahkan ke nama indeks:
class User < ApplicationRecord
redi_search index_prefix : 'prefix' do
text_field :first , phonetic : "dm:en"
text_field :last , phonetic : "dm:en"
end
end
User . search_index . name
# => prefix_users_development
Saat mengintegrasikan RediSearch ke dalam model, catatan akan secara otomatis diindeks setelah dibuat dan diperbarui dan akan dihapus dari Index
setelah dimusnahkan.
Ada beberapa metode kenyamanan lainnya yang tersedia untuk umum:
search_document
RediSearch::Document
remove_from_index
Index
add_to_index
Index
search_index
RediSearch::Index
Setelah memeriksa repo, jalankan bin/setup
untuk menginstal dependensi. Kemudian, jalankan rake test
untuk menjalankan pengujian unit dan integrasi. Untuk menjalankannya satu per satu, Anda dapat menjalankan rake test:unit
atau rake test:integration
. Anda juga dapat menjalankan bin/console
untuk perintah interaktif yang memungkinkan Anda bereksperimen.
Untuk memasang permata ini ke mesin lokal Anda, jalankan bundle exec rake install
. Untuk merilis versi baru, jalankan bin/publish (major|minor|patch)
yang akan memperbarui nomor versi di version.rb
, buat tag git untuk versi tersebut, dorong komit dan tag git, dan dorong file .gem
ke rubygems .org dan GitHub.
Laporan bug dan permintaan penarikan diterima di GitHub. Proyek ini dimaksudkan untuk menjadi ruang kolaborasi yang aman dan ramah, dan kontributor diharapkan mematuhi kode etik Perjanjian Kontributor.
Permata ini tersedia sebagai sumber terbuka berdasarkan ketentuan Lisensi MIT.
Setiap orang yang berinteraksi dalam basis kode proyek RediSearch, pelacak masalah, ruang obrolan, dan milis diharapkan mengikuti kode etik.