Solr

berkay dağlı
Artiwise AI
Published in
10 min readOct 16, 2020

Solr Apache Lucene projesinin bir parçası olan tam metin arama, çok yönlü arama, belgeleri indeksleme gibi özellikleri olan açık kaynak kodlu oldukça esnek bir arama motorudur. Temelinde arama motoru olmasına rağmen verilerin replikasyonu ve çoklu core’lara izin vermesi gibi birçok özelliğiyle bir arama motorundan daha fazlasıdır.

Solr, çeşitli kaynaklardan yapılandırılmış, yarı yapılandırılmış ve yapılandırılmamış verileri alır, depolar ve indeksler. Bununla birlikte neredeyse gerçek zamanlı olarak arama için kullanılabilir hale getirir. Solr, aynı zamanda analitik yetenekleri için de kullanılır. Facetlenmiş ürün aramaları, sosyal medya analizi vb. yapmamızı olanak sağlar. Solr tamamen açık kaynaklıdır ve şirketler genellikle bunu kendi sunucularında çalıştırır.

Solr, farklı veri türlerinde alanlı arama, kelime öbeği sorguları, yazım denetimi, joker karakterler, gruplama, otomatik tamamlama ve çok daha fazla özellikleriyle gerçek zamanlı arama yetenekleri sağlar.

İngilizce’nin yanı sıra, Çince, Japonca, Korece, Arapça, Almanca, Fransızca, İspanyolca vb. dillerde de çalışmaktadır. Dil algılama özelliğine sahiptir ve buna göre dile özgü metin analiz araçları sağlar.

Solr’ın en yaygın kullanılan özelliklerinden biri facetlemedir. Facetleme, arama sonuçlarının dizine eklenen terimlere göre kategoriler halinde düzenlenmesidir.

Bize aranan alandan kaç tane eşleşen belge bulunduğunun sayısal sayıları ile birlikte o alanın değerleri sunulur. Facetleme, kullanıcıların tam olarak aradıkları sonuçları daraltarak arama sonuçlarını keşfetmelerini kolaylaştırır. Bu yüzden bu gerçek zamanlı analizler için iyidir. Örneğin, ürün aramalarında sonuçları markaya göre kırabilirsiniz. Günlük analizlerde çıkan sonuçları gün gün kırıp sonuçları gerçek zamanlı olarak alabilirsiniz.

Solr facetleme dışında daha karmaşık işleri yapmamızı da sağlar. Örneğin farklı veri kümelerini birleştirme, kümeleme veya regresyon gibi makine öğrenimi görevlerini yapmamıza da olanak tanır.

Solr Terminoji

Döküman (Document): Bir döküman, Solr’da saklanabilen ve indekslenebilen temel bir bilgi birimidir. Dökümanlar koleksiyonlarda saklanır. Eklenebilir, silinebilir ve güncellenebilir.

Alan (Field): Veriler döküman üzerinde anahtar-değer şeklinde depolanır. Bu anahtar-değer çiftine alan denir. Buradaki anahtar alan adını, değer ise gerçek alan verilerini belirtir. Solr farklı tipte alan türlerini destekler: float, long, double, date, text, integer, boolean, vb. gibi.

Koleksiyon (Collection): Bir Solr Koleksiyonu, tek bir mantıksal indeks oluşturan bir grup shard ve core’dur. Her koleksiyonun, diğer koleksiyonlardan farklı olabilen kendi yapılandırma ve şema tanımı kümesi vardır.

Shard: Shard’lar, indekslerinizi bir veya daha fazla parçaya bölmenize ve depolamanıza izin verir, bu nedenle shard, bir koleksiyonun bir parçasıdır. Her shard bir node’da yaşar ve bir core barındırılır.

Node: Node, Solr sunucusu olarak da bilinen Solr çalıştıran tek bir Java Sanal Makinesi örneğidir. Bir node birden fazla shard barındırabilir.

Solr Nasıl Çalışır

Solr, Lucene’i indeks oluşturmak için kullanır. Sayfa merkezli bir veri yapısını anahtar kelime merkezli bir yapıya çevirir. Buradaki indeksleme de kitapta belirli kelimelerin nerede geçtiğini bulabileceğiniz herhangi bir kitabın sonunda gördüğünüz indeks kısıma benzer. Benzer şekilde Solr indeksi, sözcüklerin, terimlerin veya tümleciklerin ve bunların saklanan belgelerdeki karşılık gelen yerlerinin eşlemesini tutan bir listedir.

Solr, bu nedenle, metni doğrudan taramak yerine dizindeki anahtar sözcükleri aradığı için daha hızlı yanıtlar verir.

Solr, bir belgeyi indekslemek için alanları kullanır. Ancak, dizine eklenmeden önce veriler, Solr’ın verileri aranabilir hale getirmek için karakter filtreleri, belirteç filtreleri kullandığı bir alan analizinden geçer. Karakter filtreleri dizede bir bütün olarak değişiklik yapabilir. Ardından, belirteçler, field verilerini sözcük birimlerine veya belirteçlere böler ve daha sonra tutmaya, dönüştürmeye (ör. tüm verileri küçük harfe ayarlama, sözcük köklerini kaldırma) veya atmaya veya yenilerini oluşturmaya karar veren filtrelerden geçer. Bu son belirteçler, dizine eklenir veya sorgu sırasında aranır.

Solr Kurulumu

Java Runtime Environment (JRE) sürüm 1.8 veya üstüne ihtiyacınız olacak. Komut satırında, Java sürümünüzü şu şekilde kontrol edebilirsiniz.

java -version

Solr, https://lucene.apache.org/solr/downloads.html adresindeki Solr web sitesinde mevcuttur.

Microsoft Windows sistemleri için .zip dosyasını indirin.

İlgili dosyayı indirdikten sonra zip dosyasından çıkartın ve bin klasöründe bulunan solr.cmd dosyasınını aşağıdaki komutla çalıştırın. Bu işlemi yaptıktan sonra solr 8983 portunda hizmet vermeye başladığını görebilirsiniz.

solr.cmd start

Bu işlemi yaptıktan sonra “http://localhost:8983/” adresine gittiğiniz zaman solr’ın bize sunmuş olduğu dashboard’un açıldığını görebilirsiniz.

Dashboard ekranı açıldığında mevcutta bir core bulunmadığını görebiliriz. Verilerimizi yükleyip sorgu yapmaya başlamadan önce bir core oluşturmamız gerekir.

Solr dosyalarımızın olduğu yerden “bin” klasörüne gidip komut satırında aşağıdaki komutu çalıştırdıktan sonra core’umuz oluşmuş olacaktır.

solr create -c <coreismi>

Ben “artiwise” isminde bir core oluşturdum.

Şimdi ise yüklemek istediğimiz verileri csv formatında oluşturduğumuz core’a yükleyelim. Bunun için ben Solr dosyalarının içinde \example\exampledocs dizininde bulunan hazır books.csv dosyasını kullanacağım.

Bu dizinde bulunan “post.jar” (SimplePostTool) dosyasıyla verilerimizi Solr üzerine kolaylıkla yükleyebiliriz.

Yüklemek istediğimiz csv dosyasını bu dizine aldıktan sonra aşağıdaki komutu komut satırında çalıştırarak verilerimizi Solr’a yükleyebiliriz.

java -Dtype=text/csv -Dc=artiwise -jar example\exampledocs\post.jar example\exampledocs\books.csv

Verilerimizi yükledikten sonra solr dashboard’a tekrar gittiğimizde Solr core’unun sol taraftan seçilebilir olduğunu görebiliriz. Burada core’u seçtikten sonra sol tarafta açılan seçim yerinde query kısmına gelip “Execute Query” butonuna bastığımız zaman yüklediğimiz verilerin ekran üzerinde gözüktüğünü görebiliriz.

Solr farklı tipte alan türlerini desteklediğini daha önceden konuşmuştuk. Yüklediğimiz veriler solr üzerinde otomatik olarak field’lar oluşturdu ve field’ların tipleri gönderilen verilere göre otomatik olarak ayarlandı.

Aşağıda “name” field’ının ne tipte bir alan olarak oluşturulduğunu sol taraftaki “Schema” bölümüne gelip görebiliyoruz.

Buradaki “cat”, “name”, “price”, “inStock”, “author” alanlarının otomatik çok değerli olarak oluşturulduğunu ve bazılarının metin bazılarının sayısal değerler tuttuğunu, indekslendiğini ve kaydedildiğini görebilirsiniz.

Buradaki sayfa üzerinde istediğiniz tipte alanları oluşturup alanların nasıl bir şekilde içerde tutulması gerektiğini belirleyebilirsiniz. Buradan oluşturduğumuz fieldlar “server\solr\mycore\conf” dizininde “managed-schema” adında bir dosyanın içinde xml formatında tutulacaktır. Buradan da alanları üzerinde istediğimiz şekilde düzenleme yapmak mümkün.

Bu ekran üzerinden tek tek alan adlarını ve nasıl tutulması gerektiğini kaydetmek yerine daha kolay bir yöntem bulunuyor. Alan adlarının sonuna aşağıdaki şekilde bir ekleme yaptığımız zaman solr bu alanın otomatik olarak nasıl bir şekilde kaydedilmesi gerektiğini anlayacaktır.

Örneğin csv dosyamızda bulunan “name” alanını “name_s” şekline dönüştürdüğümüzde bu alanın artık multivalued olmadan string tipinde tutulacağını indeksleneceğini belirtiyoruz.

Aşağıda bazı örnekler bulunuyor.

_s → String

_ss → Multivalued String

_d → Double

_ds → Multivalued Double

_i → Integer

_is → Multivalued Integer

_b → Boolean

_dt → Date

_sns → Indekslenmeyen String

Yüklediğim exceldeki alanlar üzerinde değişiklikler yaptıktan sonra excel’i tekrar yüklüyorum.

Solr Sorguları

Örnek olarak yüklediğimiz verilerin üzerinden fantasy tipinde olan, fiyatı da 10’un altında olanları ve stokta bulunanları fiyatlara göre küçükten büyüğe sıralanmış bir şekilde yazar ve kitap adlarını bulmaya çalışalım. Bunun için aşağıdaki gibi bir sorgu yapabiliriz.

Gördüğünüz gibi fq(Filter query) alanına aşağıdaki filtreler eklendi. Burada dökümanların üzerinde yapmak istediğimiz filtreleri aşağıdaki gibi ekleyebiliriz.

genre_s:”fantasy”

price_d:[* TO 10]

inStock:true

Sonra bu dökümanların fiyatlara göre büyükten küçüğe sıralamak istediğimiz için sort bölümüne aşağıdaki alanı ekledik. Bu alan dökümanları price_d alanına göre büyükten küçüğe sıralanmasını söyleyecektir.

price_d desc

Eğer price_d alanına göre küçükten büyüğe sıralanmasını isteseydik aşağıdaki gibi yazabilirdik.

price_d asc

Son olarak fl(field list) alanı. Burada ise almak istediğimiz dökümanların hangi alanlarını görmek istediğimizi belirtiyoruz. Bu örnekte “author,name_s” olarak belirtildiği için filtrelediğimiz dökümanlarda sadece ilgili alanlar gözüktüğünü görebiliriz. Örneğin bu dökümanların bir de id’lerini de görmek isteseydik buraya “author,name_s,id” olarak yazabilirdik.

Resimde gördüğümüz gibi yaptığımız filtre sonucu toplam 4 adet döküman bulundu. Bulunan döküman sayısı “numFound” değerinde gözüküyor.

— — — — — — — — — — — — — — — — — — — — — — -

Ekran üzerinde bulunan farklı alanları görüyoruz. Örneğin q (query) alanıyla devam edelim. Bu kısım aslında fq alanının raw hali olarak düşünebiliriz. Örneğin az önceki örnekte fq alanına verdiğimiz filtreler yerine aşağıdaki gibi tek bir string halinde q alanına verdiğimizde aynı sonucu alabiliriz.

genre_s:”fantasy” AND price_d:[* TO 10] AND inStock:true

Burada “AND” operatörü yerine “OR” operatörünü de kullanmak mümkün.

— — — — — — — — — — — — — — — — — — — — — — —

Tipi “fantasy” olmayan kitapları çekmek istersek fq alanına aşağıdaki gibi bir filtre verebiliriz. Burada en başa eklediğimiz “-” değeri genre_s alanı fantasy olmayanlar demek olacaktır.

-genre_s:”fantasy”

— — — — — — — — — — — — — — — — — — — — — — -

Filtrelediğimiz dökümanlarda sadece “na” ile başlayan fieldları almak istersek joker karakterleri kullanabiliriz. fl alanına “na*” yazıp filtrelersek sadece “na” ile başlayan alanlar gelecektir. Bunun başka bir kullanımı da şu şekilde olabilir. Örneğin sadece string alanları görmek istiyoruz. O zaman fl alanına “*_s” diye filtrelediğimizde “_s” ile biten alanları görebiliriz.

— — — — — — — — — — — — — — — — — — — — — — -

Start değeri filtrelediğimiz dökümanları hangi değerden görmeye başlayacağımızı belirtir. Row değeri ise kaç adet dökümanı ekran üzerinde göreceğimizi belirler. Örneğin solr’da toplam 1000 adet dökümanımız olsun. Burada row değeri 10 olursa ekran üzerinde 1000 dökümandan sadece 10’tanesini görebiliriz. Eğer bu değer 100 olursa 1000 dökümandan 100 tanesini görebiliriz. Eğer start değerine 500 ve row değerine 100 yazarsak. 1000 dökümandan 500. sıradan başlayıp 100 adet döküman görmüş olacaktık.

Facetleme

Şuan için solr’ımızda örnek olması adına 18 adet döküman yüklemiştik. Fakat elimizde 1000’i geçen sayıda döküman olduğunu varsayalım. Bu dökümanların analizini yapmak istiyoruz. Bu dökümanlarla ilgili özet bir bilgi almak istediğimizi düşünelim. Örneğin elimizde 1000 adet kitap bilgileri olduğunu ve hangi türden kaç tane kitap olduğu bilgisini almak isteyelim. Bunun için facetleme yapmamız gerekecektir.

Facet bölümünü aktif ettikten sonra facet.field bölümüne özet bilgisini almak istediğimiz alanı yazalım. “genre_s” alanını yazdığımız zaman bize facet_fields kısmında;

genre_s alanı “fantasy” olan 14 adet döküman ,

genre_s alanı “scifi” olan 4 adet döküman

olduğu bilgisini kolaylıkla alabiliyoruz. Büyük döküman sayılarında bu özet bilgiyi hızlı bir şekilde alınabilir.

Bu ekranda gördüğümüz facet.query kısmında ise şunu yapabiliriz. Örneğin yapmak istediğimiz bir filtrede kaç adet döküman olduğu bilgisini öğrenmek istiyoruz. Diyelim ki fiyatı 6’dan büyük dökümanların sayısını bulmak isteyelim. Bunun için facet.query kısmına “price_d:[6 TO *]” yazdığımız zaman fiyatı 6’dan büyük olan dökümanların sayısını verecektir.

Pivot(Karar Ağacı) Facetleme

Elimizde olan dökümanlarda türleri fiyata göre kırarak özet bir bilgi almak istediğimizde pivot facetlemeyi kullanabiliriz. Örneğin “Raw Query Parameters” bölümüne “facet.pivot=genre_s,price_d” olarak yazıp filtrelediğimiz zaman yukarıdaki resimdeki gibi bir sonuç alabiliriz.

Türü fantasy olan ve fiyatı 6.99 olan 2 adet döküman vardır.

Türü fantasy olan ve fiyatı 7.99 olan 2 adet döküman vardır.

Yukarıdaki bilgileri bu sonuç üzerinden kolaylıkla çıkartabiliriz.

Facet Range Sorguları

Yüklediğimiz dökümanlar üzerinden yıl yıl kaç adet döküman olduğunu görmek istersek facet range sorgularını kullanabiliriz. Ben solr’a örnek olması için üzerinde “manufacturedate_dt“ alanı olan 5 adet döküman yükledim.

Hangi tarihte ne kadar döküman olduğunu “manifacturedate_dt” alanına göre bakarak almak için aşağıdaki sorguyu “Raw Query Parameters” bölümüne yazarak yapabiliriz.

facet.range=manufacturedate_dt&facet.range.start=2006–01–01T00:00:00Z&facet.range.end=NOW&facet.range.gap=+1YEAR

facet.range.start → Aralık sorgusuna hangi tarihten başlanılacağını belirtir.

facet.range.end → Aralık sorgusunun hangi tarihe kadar olacağını belirtir.

facet.range.gap → Ne kadar aralık olacağı bilgisini verir. Gün gün bakmak istersek +1DAY, ay ay bakmak istersek +1MONTH yazabiliriz. Haftalık bakmak için +7DAY yazılabilir.

facet.range → Aralık sorgusunun hangi tarih alanına göre yapılacağını belirtir.

Bu sorgu sonucunda resimde gördüğümüz gibi manifacturedate_dt alanı 2006 olan 3 adet, 2007 olan 1 adet ve 2008 olan 1 adet döküman olduğu bilgisini çıkartabiliriz.

Pivot ve Range Sorgularını Birleştirme

Yukarıda yaptığımız range sorgusunu aynı şekilde alıyorum.

facet.range=manufacturedate_dt&facet.range.start=2006–01–01T00:00:00Z&facet.range.end=2009–01–01T00:00:00Z&facet.range.gap=+1YEAR

Bu range sorgumuza bir tag ekliyorum.

facet.range={!tag=r1}manufacturedate_dt&facet.range.start=2006–01–01T00:00:00Z&facet.range.end=2009–01–01T00:00:00Z&facet.range.gap=+1YEAR

Gördüğünüz gibi facet.range’den sonra {!tag=r1} ekleyerek yaptığım range sorgusuna bir isim ekledim gibi düşünebiliriz. İsimlendirdiğim range sorgusunu istediğimiz pivot sorgusuyla birleştirebiliriz artık. Örneğin aşağıdaki sorguda range sorgusunu pivot sorgusuyla birleştiriyorum.

facet.pivot={!range=r1}popularity&facet.range={!tag=r1}manufacturedate_dt&facet.range.start=2006–01–01T00:00:00Z&facet.range.end=2009–01–01T00:00:00Z&facet.range.gap=+1YEAR

Bu sorguda ise dökümanların üzerindeki popularity alanını yıl yıl kırarak hangi değerinden hangi yılda ne kadar olduğu bilgisini alabiliyorum.

Bu sorgu sonucunda popularity değeri 5 olan dökümanların 1 tanesi 2006 1 tane 2007 1 tanesi ise 2008 yılında olduğunu

popularity değeri 0 olan dökümanların ise 1 tanesinin 2006 yılında olduğu gibi bilgileri bu sonuç üzerinden direkt olarak alabiliyoruz.

Ekstra Facet Filtreleri

Yaptığımız sorgularda facetlerin çıktılarını alabildik ama resimde de gördüğümüz gibi ilk olarak değeri 5 olan sonrasında değeri 0 olan sonrasında ise değeri 7 olan sonuç geldi. Facetleri de kendi içlerinde sıralayabilmek mümkün.

Yaptığımız sorguya facet.sort=index dersek alfabetik olarak sıralı facetler gelir. Fakat facet.sort=value dersek hangi facetten en fazla varsa o ilk sırada gelecektir.

— — — — — — — — — — — — — — — — — — — — — -

Biraz yukarıda dökümanları çekerken start ve row parametrelerinin ne işe yaradıklarını anlatmıştık. Bu parametreler genel olarak döküman üzerinde paging yapma işi için kullanılırlar. Sonuçların belli bir kısmını alabilmemizi sağlarlar.

Peki ya facetler üzerinde paging yapmak istersek ?

O zaman “facet.offset” ve “facet.limit“ parametrelerini kullanabiliriz. facet.offset start’ parametresine denk gelir. “facet.limit” ise rows parametresine denk gelecektir.

Facet.offset parametresi ile hangi sıradan facetleri alacağımızı söyleriz. Facet.limit ile ise kaç adet facet alacağımızı belirtiriz. Bu iki parametre ile facetler üzerinde paging yapmak mümkün.

— — — — — — — — — — — — — — — — — — — — — — -

Belli bir sayısının altında olan facetleri almak istemediğimiz zaman ise facet.mincount parametresini kullanabiliriz. Örneğin facet.mincount=2 olarak belirlersek sayıları 2’nin altında olan facetler ekranımızda gözükmeyecektir.

Referanslar

https://lucene.apache.org/solr/guide/6_6/index.html

https://sematext.com/guides/solr/

https://en.wikipedia.org/wiki/Apache_Solr

--

--