İnternette açık kaynak kodlu ve oldukça başarılı arama motorları (lucene gibi) mevcut, fakat bu arama motorlarını yapılandırmak ve kullanmak çok zor olabiliyor. Yakın zamanda çıkan sphinx birçok proje için başarılı bir alternatif oluşturuyor.
Sphinx mysql ve postgresql ile çalışan, hızlı ve kolay configure edilen bir arama motorudur. Tanımlanan veritabanına bağlanarak belirli bir sorgunun sonuçlarını indeksler ve arama yapılmasını sağlar. İndeksleme ve arama hızı çok iyi olduğundan kullanımı hergün artmaktadır.
Sphinx'i kullanabilmek için API'ler de (Php, Python, Java vs) mevcuttur. Ayrıca mysql içerisinden Sphinx Storage Engine ile de arama yapılabilir.
Bu yazıda Sphinx'i linux üzerine kurarak örnek bir tabloyu indeksleyeceğiz. Daha sonra da bu indeks üzerinde sphinx'in client'i ile arama yapacağız.
Kurulumu
Sphinx'in kurulu oldukça basittir. Klasik bir linux programı gibi kurulabilir.
# wget http://www.sphinxsearch.com/downloads/sphinx-0.9.8.tar.gz
# tar xvfz sphinx-0.9.8.tar.gz
# cd sphinx-0.9.8Sphinx'i derlerken mysql desteği ve 64 bit ID desteği vereceğiz. 64 bit desteği vermezsek kullanabileceğimiz en büyük ID 2^32 yani 4.294.967.296 olacaktır ve bu da bizim sistemimiz için küçük kalabilir. Eğer sizin için gerekli olmadığını düşünüyorsanız "--enable-id64" parametresini kaldırabilirsiniz. Aşağıdaki komutun çalışabilmesi için sisteminizde mutlaka mysql-devel paketlerinin kurulu olması gerekiyor.# ./configure --enable-id64 --with-mysql
# make
# make installSphinx'in YapılandırılmasıElimizde contenttest adında bir veritabanının olduğunu düşünelim. Ve bu veritabanındaki content tablosunun yapısı şu olsun :
CREATE TABLE `contents` (
`id` bigint(20) unsigned NOT NULL default '0',
`servicename` varchar(45) NOT NULL,
`content` char(200) NOT NULL,
`url` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
)Tabloda sadece content kolonunda arama yapacağız, fakat aramayı özelleştirebilmek için servicename kolonunu da indekse dahil ediyoruz. İndeksleme için kullanacağımız sorgu şu olucak :SELECT id,servicename,content from contents;İndeks için kullanılacak sorguda MUTLAKA unique bir ID kolonu olmalı ve bu kolon sorgunun ilk bölümünde kullanılmalıdır. Aksi takdirde sphinx indeksleme yaparken hata verecektir.Sphinx'de arama yapıldığında sonuç olarak sadece ID getirmektedir. Bu yüzden sorgunun içinde unique bir id kolonu olmalıdırSphinx'in yapılandırma dosyası /usr/local/etc/sphinx.conf 'u aşağıdaki şekilde düzenledik :
source src_contents{type = mysqlsql_host = localhostsql_user = myusersql_pass = mypasssql_port = 3306sql_db = contenttestsql_query_pre = SET NAMES utf8;sql_query = SELECT id,servicename,content from contents;}index idx_content{source = src_contentspath = /data/sphinxdata/contenthtml_strip = 1charset_type = utf-8charset_table = A->a, B->b, C->c, U+C7->c, U+E7->c, D..G->d..g, U+11E->g, U+11F->g, H->h, I->i, U+131->i, U+130->i, J..O->j..o, U+D6->o, U+F6->o, P..S->p..s, U+15E->s, U+15F->s, T..U->t..u, U+DC->u, U+FC->u, V..Z->v..z, _, a..z,[,],0..9}indexer{mem_limit = 256M}searchd{address = 127.0.0.1port = 3312log = /var/log/searchd.logquery_log = /var/log/query.logpid_file = /var/log/searchd.pidmax_matches = 1000}
Görüldüğü gibi Sphinx'in yapılandırma dosyası 4 bölümden oluşmaktadır.
Source bölümünde bir isim verilerek (source src_contents) veritabanına nasıl bağlanılacağı ve indekslemede kullanılacak sorgu tanımlanmaktadır. Bu bölümdeki sql_query_pre parametresi ile sphinx veritabanına bağlandığında indekslemeden önce mysql'e hangi sorguyu göndereceği tanımlanmaktadır. Karakter problemleri olmaması için ve veritabanımız UTF8 olduğundan burada "SET NAMES utf8" sorgusu ile karakter set tanımlanıyor. İsteğe göre başka sorgular da tanımlanabilir.
Index bölümünde ise indeksleme işlemini etkileyen özellikler tanımlanır. İndeksleme yapılırken hangi kaynağın kullanılacağı source parametresi ile ve indeksin disk üzerinde nerede tutulacağı ise path ile tanımlanır. html_strip parametresi ile indeksleme yapılırken veritabanındaki HTML tag'lerinin temizlenip temizlenmeyeceği belirlenir. Örneğin tabloda "<a>test</a>" şeklinde bir veri varsa ve "html_strip = 1" ise veri "test" şeklinde indekslenecektir. charset_type ile veritabanın hangi karakter setinde oluşturulduğu tanımlanır.
charset_table ise indeksleme yapılırken hangi karakterin nasıl indeksleneceğini tanımlar. Sphinx Türkçe karakterleri tanıyamadığı için indeksleme yapılırken bu karakterleri dönüştürmek en mantıklı yoldur. Yukarıdaki tablodan da anlaşıldığı üzere bütün büyük harfler küçük harflere (örneğin A->a) ve Türkçe karakterler latin karşılıklarına (ü->u, ç->c gibi) dönüştürülerek indeksleme yapılıyor. Örneğin Küçük kelimesi kucuk olarak indeksleniyor. Arama yapılırken de sphinx kelimeleri dönüştürerek arama yaptığı için herhangi bir sorun olmamaktadır. Yani aramada "küçük" kelimesi kullanılırsa sphinx bunu "kucuk" kelimesine dönüştürüp aramaları yapıyor.
indexer bölümü ise indeksleme yapan programa limitler tanımlanmaktadır. Burada mem_limit ile indeksleme anında maksimum ne kadar bellek kullanacağı tanımlanmıştır.
searchd, arama için kullanılan programın özelliklerini tanımlamaktadır. address ile hangi IP adresini dinleyeceği, port ile de hangi portta çalışacağı tanımlanır. Searchd programının log'larının nerede tutulacağı log ile belirlenir. query_log ise yapılan aramalarla ilgili istatistiklerin tutulacağı dosyanın yerini belirler. pid_file , searchd'nin process id'sinin hangi dosyada tutulacağını gösterir. max_matches ile aramalarda en fazla kaç sonuç döndürüleceği tanımlanır.
İndeksleme yapmak için aşağıdaki komut kullanılır :
# /usr/local/bin/indexer --config /usr/local/etc/sphinx.conf idx_content Yukarıdaki komutta --config ile yapılandırma dosyasının nerede olduğu, en sondaki idx_content parametresi ile de indeksin ismi tanımlandı.Komut çalıştırıldıktan sonra indeksleme yapılmaya başlanacaktır. İşlemin süresi verinin büyüklüğüne ve sorgunun ne kadar kompleks olduğuna göre değişecektir.
Sphinx ile Arama
İndeksleme tamamlandığında bu indeksi kullanarak aramaları yapmamızı sağlayacak searchd adlı daemon’u çalıştırmalıyız. Bu daemon yapılandırma dosyasında tanımladığımız adres (127.0.0.1) ve portu (3312) dinlemektedir.
# /usr/local/bin/searchdAramaları yapmak için yine sphinx ile gelen search komutunu kullanacağız.Yukarıdaki komutla idx_content indeksinde test kelimesini aratarak ilk 10 sonucu istedik. “test” kelimesi 476 satırda toplam 688 defa bulunmuş. Yani bazı satırlarda en az 2 defa kullanılmış. Gelen sonuçlardaki “document=2500042872” bölümü test geçen satırın ID’sini belirtiyor. Veritabanına bağlanıp doğru sonuç gelip gelmediğini test edebilirsiniz :
# search -i idx_content -l 10 test
Sphinx 0.9.8-id64-release (r1371)
Copyright (c) 2001-2008, Andrew Aksyonoff
using config file '/usr/local/etc/sphinx.conf'...
index 'idx_content': query 'test ': returned 476 matches of 476 total in 0.001 sec
displaying matches:
1. document=2500042872, weight=2
2. document=1200021423, weight=2
3. document=2500011157, weight=2
4. document=1200081879, weight=2
5. document=2500041669, weight=2
6. document=2500072784, weight=2
7. document=1200000397, weight=2
8. document=1200010161, weight=2
9. document=1200038948, weight=2
10. document=1200040882, weight=2
words:
'test': 476 documents, 688 hits
mysql> SELECT id,servicename,content from contents where id=2500042872;
+------------+---------+----------------------------+
| mcid | content | text |
+------------+---------+----------------------------+
| 2500042872 | test | motorsiklet test sürüşleri |
+------------+---------+----------------------------+
Sonuçlardaki “weight=2” bölümü ise aranan verinin ne kadar çok bulunduğunu gösteren bir puandır. Bu konu başka bir yazıda ayrıca anlatılacaktır.
Yaptığımız aramayı daha da genişletebiliriz. Eğer content kolonu grup olanlar içinde test kelimesini aratmak istersek şu komutu kullanabiliriz :
# search -i idx_content -l 10 –e “test @content grup”
Sphinx ile daha ayrıntılı bilgiye web sayfasından ulaşılabilir : http://www.sphinxsearch.com/Sphinx'i Mysql içinden nasıl kullanacağınız hakkında yazıma ulaşmak için :
http://blog.salihgiray.com/2008/09/sphinxi-mysql-iinden-kullanmak.html
4 comments:
selam,
veritabanin zaten utf8 degil mi?
charset_table ile turkce karakterleri silmeye gerek var mi?
Sphinx, db utf8 bile olsa İngilizce ve Rusça diller dışındaki karakterleri tanıyamıyor. Bu yüzden Türkçe karakterleri ingilizce karakterlere dönüştürmek gerekiyor.
Ayrıntılı bilgi :
http://www.sphinxsearch.com/docs/current.html#charsets
ben de tam şu charset_table da nedir diye bakınıyordum.
yardımın için sağol.
Yorum Gönder