Tidak ada banyak informasi tentang Sphinx yang kami inginkan. Kelebihan artikel tidak ada salahnya.
Langkah pertama dalam menguasai Sphinx membantu saya membuat artikel. Membuat mesin pencari pengantar di Sphinx + php dan contoh pencarian Sphinx pada proyek nyata - toko onderdil mobil Tecdoc Saya menyarankan Anda untuk mulai dengan mereka.
Untuk beberapa waktu, pencarian melalui LIKE untuk setiap kata dari kueri berfungsi di situs saya. Saya menginginkan lebih, dan berikut adalah beberapa kasus yang sekarang akan ditangani dengan benar:
- Bentuk kata. Output untuk "sekrup" dan "sekrup" harus sama.
- Cari berdasarkan fragmen kata.
- Cari nomor yang bukan bilangan bulat. Titik pemisah dan koma.
- Huruf y
- Kesalahan umum. Misalnya, "Shock Absorber".
- Sinonim Regulator dan ESC.
- Bahasa mAh dan mAh, B dan V, AAA Latin dan Cyrillic.
- Word terbuat dari huruf dan angka. 10x15x4, 6000mAh
Bagian sumber dan penyortiran opsional
Masalahnya pertama-tama harus berisi item dalam stok, kemudian absen sementara, lalu diarsipkan. Dan ketiga kelompok ini harus disortir berdasarkan relevansinya. Untuk melakukan ini, Anda perlu mengatur atribut. Dalam kasus saya, ini adalah bidang clearance dan in_stock dari bagian sphinx.conf sumber
sql_query = \ SELECT id, `art`, `name`, `clearance`, `in_stock` \ FROM items_zip WHERE show_flag=1 sql_attr_bool = clearance sql_attr_uint = in_stock
Bidang-bidang ini akan digunakan dalam menghasilkan keluaran dalam PHP. Saya akan jelaskan di bawah ini.
Bagian indeks di sphinx.conf
morfologi = stem_enru
Morfologi memecahkan masalah pertamaku. Pencarian untuk 'bantalan', 'bantalan', 'bantalan' akan menghasilkan hasil tunggal.
Batang (stem_enru) lebih cepat, lemmas (lemmatize_ru) lebih akurat. Saya hanya mencoba stamms. Pilihan ini akan memengaruhi kamus Anda untuk penggantian bentuk kata. Ingin berubah - Anda harus menulis ulang.
min_word_len = 1
Mengindeks kata apa saja.
html_strip = 1
Hapus tag html
min_infix_len = 1
Pencarian akan berada di fragmen kata. Mengindeks fragmen hingga 1 huruf. Karena saya memiliki kurang dari 10.000 item dalam basis data, saya tidak menyimpan pada indeks.
expand_keywords = 1
Secara otomatis mengarahkan kueri ke bentuk "(running | running | = running)". min_infix_len dan expand_keywords akan menyebabkan RV 2205 mengeluarkan RV2205. By the way, tanda hubung adalah pemisah yang setara dengan spasi. Jadi RV-2205 akan memberikan RV2205 yang sama.
charset_table = 0..9, A..Z-> a..z, _, a..z, U + 410..U + 42F-> U + 430..U + 44F, U + 430..U + 44F, U + 401-> U + 0435, U + 451-> U + 0435
Kami membawa alfabet Latin dan alfabet Sirilik dalam huruf kecil. ganti dengan e.
blend_chars = +, &, U + 2C, U + 2E
Saya memiliki banyak angka non-integer. Mereka harus diindeks sepenuhnya. U + 2C dan U + 2E adalah titik dan koma. Misalnya, 1,25 akan diindeks sebagai '1,25', '1' dan '25'.
regexp_filter = (\ d +) \, (\ d +) => \ 1. \ 2
Tempat desimal dalam angka dapat dipisahkan dengan tanda titik dan koma: "1,75", "1,75". Kami membawa semuanya ke intinya
Sinonim dan kesalahan ketik
Satuan ukuran dapat ditulis dalam bahasa Rusia atau Inggris: mm-mm, mAh-mAh, mW-mW. Tambahkan ke kamus sinonim, jalur yang ditentukan dalam bentuk kata: "mach> mah". Saya memilih bahasa untuk indeks sesuai dengan preferensi saya sendiri.
Tanda ~ menunjukkan untuk menerapkan penggantian setelah penangan morfologi. Ini memungkinkan Anda untuk tidak menulis semua bentuk kata dan bukannya aturan untuk 'kerak', 'kerak', 'kerak' tulis "~ gabus> tubuh"
Daftar saya selesai:
~ > esc > esc > mah ~ > ~ > ~ > buzz ~ > buzz ~ > buzz ~ > buzz ~ > buzz ~ > ~ > ~ > li-po > lipo ~ > ~ > > > vtx > ~ > lollipop > lolipop battery > ~ > ~ > ~ > mkF > > BEC > BEC ~ > LED > ~ > driver > ~ > ~ > > AAA > AA > M mm > > mW > V > A deans > t-plug tplug > t-plug
Menempelkan huruf ke angka
Terkadang angka adalah bagian dari nama (mis. LCD5208D), tetapi lebih sering merupakan karakteristik (100mAh, 10x15x4mm). Pisahkan semua angka dari huruf dan indeks.
Ini akan menyelesaikan beberapa masalah:
- Seseorang akan mencari 'bantalan 10x15x4', seseorang 'bantalan 15x10x4'. Angka yang diindeks akan menghasilkan output yang benar.
- Unit pengukuran dapat atau tidak dapat dipisahkan oleh spasi dari nomor: "1.75mm", "1,75 mm".
- Untuk judul, ini juga berguna. Output yang benar adalah dalam tiga opsi perekaman LCD-5208, LCD 5208 dan LCD5208
Sebelum menulis ekspresi reguler ke angka yang terpisah, Anda harus menyatukan pembatas. Penting untuk diingat bahwa ekspresi reguler dijalankan semua dan berurutan.
Kami menghapus x, dia dan bintang dalam ukuran seperti 10x4x4 M3x10:
regexp_filter = (\d+)[x\x{0445}\*] => \1 x
Jatuhkan ekor:
regexp_filter = (\d*\.?\d+)(\D+) => \1 \2
Dan kepala:
regexp_filter = (\D+)(\d*\.?\d+) => \1 \2
Kami membuang "mm", karena sering tidak disebutkan dalam nama produk.
Buat file stop.txt dan tulis dalam stopwords.
Konten:
mm
Sekarang sedikit tentang PHP
Sphinxapi akan cepat atau lambat akan rusak. Kami akan menggunakan Sphinxql. Untuk melakukan ini, hubungkan ke database. Dalam kasus saya, Sphinx terhubung melalui hosting, sepertinya ini:
$opt = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => TRUE, ); $dsn = 'mysql:host=127.0.0.1;port=9306;'; $this->pdo = new PDO($dsn, DB_USER, DB_PASS, $opt);
Dan semua komunikasi dengan Spinxql adalah satu SELECT mentransmisikan teks kueri yang difilter
$stmt = $this->pdo->prepare("SELECT `id`, WEIGHT() as `w`, in_stock>0 AS stock FROM `items` WHERE MATCH ('".$search."') ORDER BY clearance ASC, stock DESC, w DESC LIMIT ".$limit." OPTION field_weights=(name=10, art=3, cat_names=3, model_names=3)");
SphinxQL tidak memahami ekspresi di bagian ORDER BY sorting, jadi WEIGHT () dan in_stock> 0 harus dimasukkan ke dalam bidang. Omong-omong, batas default hanya 20.
Penyortiran pertama akan menghasilkan item dalam stok, kemudian absen sementara, lalu diarsipkan. Dan ketiga kelompok ini akan diurutkan berdasarkan relevansi (berat).
Melalui field_weights kami menetapkan bidang mana yang akan memiliki bobot lebih.
Dengan menyelesaikan permintaan, kami mendapatkan array id yang diurutkan. Namun, sayangnya, pemilihan data melalui WHERE id IN () akan melanggar penyortiran ini. Harus membentuk permintaan Anda untuk setiap id.
Pada fase debugging , SHOW META permintaan segera setelah permintaan SELECT sangat membantu. Terutama untuk memeriksa bentuk kata kamus dan filter ekspresi reguler. Anda dapat melihat daftar kata kunci di mana kueri telah diperluas.
Sql_query yang rumit
Kami menjual suku cadang. Saya memutuskan untuk menambahkan nama kategori produk dan nama model yang suku cadangnya dimaksudkan untuk ditambahkan ke indeks. Tetapi setiap produk dapat diikat ke beberapa kategori sekaligus dan cocok untuk beberapa model. Dan saya menemukan fungsi GROUP_CONCAT yang memungkinkan Anda mendapatkan data dengan mengelompokkannya menjadi sebuah string. Sebagai contoh, bidang categories.name akan berisi semua kategori dari items_zip.id yang dipilih dipisahkan oleh spasi.
SELECT items_zip.id, `art`, items_zip.`name`, `clearance`, `in_stock`, GROUP_CONCAT(DISTINCT categories.name SEPARATOR ' ') AS cat_names, GROUP_CONCAT(DISTINCT items.family SEPARATOR ' ') AS model_names FROM items_zip LEFT JOIN items_cat ON items_cat.item_id=items_zip.id LEFT JOIN categories ON categories.id=items_cat.cat_id LEFT JOIN zip_comp ON zip_comp.zip_id=items_zip.id LEFT JOIN items ON zip_comp.model_id=items.id WHERE items_zip.show_flag=1 GROUP BY items_zip.id