Laravelde yapmış olduğum bir uygulamada gelişmiş bir arama sistemine ihtiyaç duydum. Bunun içinde yaptığım araştırmalarda elasticsearch ve algolia seçenekleri karşıma çıktı. elasticsearch için jdk kullanıldığını gördüm ve vazgeçtim. Algolia'da ise 10.000 data kaydına kadar ücretsiz izin veriyor. Ben daha 2 tabloda 10.000 kayıta ulaşmak üzereyim. Bu da beni ücretli hizmet almaya yöneltiyor ki bunu yöneticilere kabul ettirmem mümkün değil. Algolia gibi hızlı ve esnek bir arama işlemi için nasıl bir yol izlememi önerirsiniz? Bu konuda tavsiye edebileceğiniz bir paket uygulama mevcut mu? Elasticsearch'ü araştırdım lakin biraz kafamı karıştırdı diyebilirim. Entegrasyonu algolia kadar kolay değil gibi geldi.
merve
loc Merhaba, üzerinden zaman geçmiş ancak son olarak neye karar verdiniz? Ben de bir projemde algolia kullanmaya karar vermiştim ancak 10.000 kayıt sınırını burada öğrendim. 25K kayıtlı kullanıcı (giderek artan) arasında, instagram kullanıcı arama modülünün birebir aynısını yapmaya çalışıyorum.
evrend
Arama işi biraz külfetli bir iştir. Elastic Searc alternatifleri olarak Sphinx, Lucene, Solr, Xapian incelenebilir. Ama bunların kurulumu, arama yapılacak içeriklerin indexlenmesi başlı başına birer iştir. Bunların dışında Laravel ile uyumlu php tabanlı teamtnt/tntsearch paketi mevcut. Full text arama motorunu php ile geliştirmişler. Denemedim ama bunun haberini LaravelNews'de görmüştüm. Tam sizin aradığınız şey aslında, denemekte yarar var. https://github.com/teamtnt/tntsearch
loc
evrend wrote: Arama işi biraz külfetli bir iştir. Elastic Searc alternatifleri olarak Sphinx, Lucene, Solr, Xapian incelenebilir. Ama bunların kurulumu, arama yapılacak içeriklerin indexlenmesi başlı başına birer iştir. Bunların dışında Laravel ile uyumlu php tabanlı teamtnt/tntsearch paketi mevcut. Full text arama motorunu php ile geliştirmişler. Denemedim ama bunun haberini LaravelNews'de görmüştüm. Tam sizin aradığınız şey aslında, denemekte yarar var. https://github.com/teamtnt/tntsearch
Şimdi şöyle bir durum söz konusu. Elimde 50-60.000 lik kayıt var şuanda. Eğer yanılmıyorsam bunların hepsini ilk seferde indexlettireceğim daha sonra yeni veri gelince ekleme, değişince güncelleme silinince de silme işlemi yapacağım. Her seferinde yeniden indexletirsem bu gerçekten de zaman alır. tnt search paketini deneyeceğim. Lakin yolun başındayken veri büyüdükçe beni yarı yolda bırakmayacak birşey yapmak istiyorum.
mgsmus
10 bin kayıt için ücretli arama düşünmeye gerek yok. MySQL'in kendi fulltext arama özelliğini de kullanabilirsiniz, birkaç milyon kaydı rahatlıkla halleder.
evrend
Aslına bakarsanız 50-60 bin kayıt günümüz veritabanları için hiç bir şey değildir. Ben bir uygulamamda elastic search kullanmıştım. Rakamlar bu rakamlara yakındı. Kullanma sebebim arama yapılacak alanlardaki verilerin büyüklüğü ve mantıklı arama algoritması ihtiyacı. Üzerinden iki yıl kadar geçti, hatırladığım kadarıyla 5dkda bir falan indexleme yaptırmıştım. Buna rağmen hala sorunsuz çalışıyor. Ne sıklıkla güncelleme yapacaksınız? Bunu uygulamanızın veri akışına göre siz kararlaştırmalısınız. Eğer laravel modelindeki update, create, delete eventleri ile tetikleyebilirseniz, çok daha güzel olur tabiki ama ben böyle yapmadığım için nasıl yapılır, yapılır mı bilmiyorum.
loc
evrend wrote: Aslına bakarsanız 50-60 bin kayıt günümüz veritabanları için hiç bir şey değildir. Ben bir uygulamamda elastic search kullanmıştım. Rakamlar bu rakamlara yakındı. Kullanma sebebim arama yapılacak alanlardaki verilerin büyüklüğü ve mantıklı arama algoritması ihtiyacı. Üzerinden iki yıl kadar geçti, hatırladığım kadarıyla 5dkda bir falan indexleme yaptırmıştım. Buna rağmen hala sorunsuz çalışıyor. Ne sıklıkla güncelleme yapacaksınız? Bunu uygulamanızın veri akışına göre siz kararlaştırmalısınız. Eğer laravel modelindeki update, create, delete eventleri ile tetikleyebilirseniz, çok daha güzel olur tabiki ama ben böyle yapmadığım için nasıl yapılır, yapılır mı bilmiyorum.
Uygulamayı anlatmam gerekirse şirket içi intranet uygulaması. İçinde CRM modülü de var. Sadece başlı başına CRM kısmı bile nasıl bir veriye sahip olacağının kanıtıdır. Proje, proje içi etkileşimler, teklifler, raporlar, stok gibi bir sürü veri mevcut. 60 bin kayıt 4 ayda oluştu. Bundan sonraki süreçte nasıl bir kayıt olacağını ben bile kestiremiyorum ve daha önceden hiç büyük veritabanlarıyla iş yapmamıştım onu da en başından söyleyeyim. Şimdi benim yapacağım şey şu. Uygulamanın yeni versiyonunu yayına aldığımda (bu mesai saatleri dışında olacak tabi) komple bir indexleme yapıp bundan sonraki işlemleri sadece değişen ve eklenen veriler üzerinde yapmayı planlıyorum. Herhalde böyle bir olay vardır diye düşünüyorum.
evrend
Ben öyle yapmamıştım ama yapılabiliyormuş. Bu şekilde teker teker verileri güncellerseniz bile belirli aralıklarla komple indexleme yaparak, hatalı veri olma ihtimalini düşürebilirsiniz.
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html
loc
@evrend
elastic search için yapılmış bir paket buldum. https://github.com/mustafaaloko/elasticquent5
Gayet sağlıklı çalışıyor şuanda. Örneğin eklenen veriyi indexlemek için şöyle bir method göstermiş
$book->addToIndex();
Model içinde yer alan static boot methodunda creating işlemi için $book->addToIndex(); tanımlasam anında indexleme işlemi gerçekleşir sanırım diye düşünüyorum.
evrend
loc wrote: @evrend
elastic search için yapılmış bir paket buldum. https://github.com/mustafaaloko/elasticquent5
Gayet sağlıklı çalışıyor şuanda. Örneğin eklenen veriyi indexlemek için şöyle bir method göstermiş
$book->addToIndex();
Model içinde yer alan static boot methodunda creating işlemi için $book->addToIndex(); tanımlasam anında indexleme işlemi gerçekleşir sanırım diye düşünüyorum. :)
Böyle bir kullanım varsa gerçekten çok iyiymiş. Bilgilendirme için teşekkürler. Kullandıktan sonraki tecrübelerini de paylaşırsan herkes için faydalı olacaktır.
loc
Malesef böyle bir kullanım yokmuş. Lakin bunun için Event Handler kullandım. Bu şekilde çalışıyor. Bunda update olayı yok yalnız. Orası biraz kötü...
loc
Bir kötü özellik daha farkettim. Arama yaparken mesela Örnek kelimesiyle başlayan bir içeriğim var. Örne şeklinde arama yaptığım zaman sonuç gelmiyor. Kesinlikle tam kelimeyi yani Örnek yazmam gerekiyor. Bu konuda bir çözümü olan var mı?
Bir de şöyle bir durum var tabi. Gelen içeriğe göre url yapısı oluşturmam gerekiyor lakin index tipini arama sonucunda alamadığım için ayırt etme işlemi yapamıyorum. Daha doğrusu jquery easyautocomplete eklentisinde ayırt edecek bir özellik bulamadım diyebilirim. Bir noktadan sonra elim kolum bağlı kaldım resmen
evrend
Öncelikle ElasticSearch kullandıysan arama algoritmasını kendin belirliyorsun. Match, Equal gibi filtreler var, % kaç eşit olursa kayıtlar gelsin gibi oldukça detaylı arama işlemleri geliştirebilirsin. Benim nasıl kullandığımı paylaşayım fikir verir. Dediğim gibi 2 seneyi geçti yapalı o yüzden detaylarını dökümandan incelemek lazım. Aşağıdaki kodu hem ElasticSearch client nesnesinin parametrelerini döndürmesi hemde paginate ile kullanabilmek için hazırlamıştım. Fikir verebilir.
private function getByPageWithQuery($page = 1, $limit = 15)
{
 $page -= 1;
 $from = $page * $limit;

 $should_array = array();
 if (Input::has('string')) {
 array_push($should_array, array(
 'multi_match' => array(
 'query' => SddForm::searchString(Input::get('string')),
 "fields" => [ "karar_metni", "karar_kavram"],
 "type" => "phrase_prefix"
 )
 ));

 array_push($should_array, array(
 'multi_match' => array(
 'query' => SddForm::searchString(Input::get('string')),
 "fields" => [ "karar_metni", "karar_kavram"],
 "type" => "cross_fields",
 )
 ));
 }

 if (Input::has('esas_no')) {
 array_push($should_array, array(
 'match' => array('esas_no' => array('query' => Input::get('esas_no'), "type" => "phrase")),
 ));
 }

 if (Input::has('karar_no')) {
 array_push($should_array, array(
 'match' => array('karar_no' => array('query' => Input::get('karar_no'), "type" => "phrase")),
 ));
 }

 if (Input::has('karar_tarih')) {
 array_push($should_array, array(
 'match' => array('karar_tarih' => array('query' => str_replace('.', '/', Input::get('karar_tarih')), "type" => "phrase")),
 ));
 }

 if (Input::has('kurum_id') && Input::get('kurum_id') != "") {
 array_push($should_array, array(
 'match' => array('kurum_id' => array('query' => Input::get('kurum_id'), "type" => "phrase")),
 ));
 }

 if (Input::has('karar_sonuc_tip_id') && Input::get('karar_sonuc_tip_id') != "") {
 array_push($should_array, array(
 'match' => array('karar_sonuc_tip_id' => Input::get('karar_sonuc_tip_id')),
 ));
 }

 if (count($should_array) < 1) {
 $sort_array = array("created_at" => array("order" => "desc"));
 } else {
 $sort_array = array();
 }

 $params = array(
 'index' => 'kararlar',
 'type' => 'jdbc',
 'body' => array('query' => array(
 'bool' => array(
 'should' => $should_array,
 ),
 ),
 "from" => $from,
 "size" => $limit,
 "sort" => $sort_array,
 ),
 );
 return $params;
}
İndex tipi derken neyi kastettiğinizi anlamadım? Arama yapmanız gereken her tablo için ayrı index oluşturmadınız mı?
loc
Oluşturdum. Lakin şöyle bir durum var. Örneğin. Kontroller yapım şu şekilde:
 public function search(Request $request){
 
 $key = $request->input('phrase');
 $companies = $this->company->search($key);

 $projects = $this->project->search($key);

 return \Response::json([
 'companies' => $companies,
 'projects'	=> $projects

 ]);

 }
Buradan aldığım çıktı da şu şekilde:
https://codeshare.io/yKaSQ
Javascript kodunda sonucun ilgili sayfaya gitmesi için link yapısını ayırt etmem gerekiyor. Lakin template kısmına firma mı proje mi belirtemediğim için tıkandım kaldım.