"Vapur" kelimesi

"Vapur" kelimesini herhalde İstanbul gibi deniz kıyısında yaşayanlar en iyi bilir. Peki "buhar gücüyle çalışan gemi" anlamına gelen bu kelimenin Latince "vapor" kelimesinden türetildiğini ve "buhar" anlamına geldiğini biliyor muydunuz?

karalama

Bütün bu taşınmalar, ayrılıklar, vedalar bana insanın hiçbir zaman kendi arkadaşlarını seçemeyeceği ve bunun sadece ve sadece adına kader denilen o esrarengiz güç tarafından belirlendiği fikrini benimsetti.

Günün sözü

"Hayat o kadar berbat olamaz," diye düşünürüm bazen. "Ne de olsa, sonunda insan Boğaz'da bir yürüyüşe çıkabilir."


İstanbul: Hatıralar ve Şehir. Orhan Pamuk. İletişim Yayınları, 2003.

{Ankara için ne var allaşkına :) }

Flickr Interestingness

I've just came across a patent application filed by Flickr co-founders Caterina Fake and Stewart Butterfield, among others. It describes the logic behind the interestingness feature of Flickr, which is one of my favorite services rendered by the photo sharing web site.

I'm not familiar with the patent application procedure, I wonder what the outcome has been. It was filed about 3 years ago after all. It does talk about some common knowledge, by common knowledge I mean knowledge that researchers in data mining, collaborative filtering areas know about. Does that make it objectionable?

Overall, it is an interesting read to learn more about the behind the scene workings of my favorite photography web page.

ris to bibtex etc. - Changing citation format

I've just found this great web site which has several programs for converting from one bibliography format to another. Now I can easily and effortlessly cite that Nature magazine article in my thesis :) ris2xml and then xml2bib does the trick. Great!

Latex Makefile

I'm currently in the process of writing my thesis. I had created my own Makefile but this one here is one Makefile I'm happy that I found about. It has many latex utilities I had not known before (like texi2dvi) and it makes everything much easier for the latex writer.

I've made some customizations so that evince is fired instead of xdvi and I've set the environment variable stuff inside the Makefile. I've also changed the default target (using .DEFAULT_GOAL special variable). Change as you please, and enjoy writing your work (instead of pulling your hair because of Latex!).

Google - How it all started

"He who controls the search engine, controls the Internet."

Abstract:

In this paper, we present Google, a prototype of a large-scale search engine which makes heavy use of the structure present in hypertext. Google is designed to crawl and index the Web efficiently and produce much more satisfying search results than existing systems. The prototype with a full text and hyperlink database of at least 24 million pages is available at http://google.stanford.edu/ To engineer a search engine is a challenging task. Search engines index tens to hundreds of millions of web pages involving a comparable number of distinct terms. They answer tens of millions of queries every day. Despite the importance of large-scale search engines on the web, very little academic research has been done on them. Furthermore, due to rapid advance in technology and web proliferation, creating a web search engine today is very different from three years ago. This paper provides an in-depth description of our large-scale web search engine -- the first such detailed public description we know of to date. Apart from the problems of scaling traditional search techniques to data of this magnitude, there are new technical challenges involved with using the additional information present in hypertext to produce better search results. This paper addresses this question of how to build a practical large-scale system which can exploit the additional information present in hypertext. Also we look at the problem of how to effectively deal with uncontrolled hypertext collections where anyone can publish anything they want.


You can read the paper online here.


The rest, as they say, is history.

Problem of huge number of interleavings in MPI

I've just came across a verification tool for MPI programs. Even debugging sequential programs written in a language like C/C++ can be a quite daunting task because of the complexity it involves; all those pointer operations including memory management, cryptic C++ template errors, the time wasting edit-compile-test procedure of compiled languages etc. Dynamic languages are easier in my opinion because they are more simple with automatic garbage collection, duck typing and the interactive shells that enables you to test your programs and/or snippets much faster. Parallel programming introduces other complexities. You have to watch out for deadlocks, race conditions etc. and thinking/visualizing them is much more harder than sequential programs. The human brain is more suitable for small number of parallel jobs, it is most intuitive to understand serial programs. Maybe this is because of the way we had been taught at the universities because parallel programming is not so widespread right now.

Simply thinking about the number of different runnings of parallel programs can be daunting. The simple example in the ISP website is enlightening:

It is well known that even an MPI program with five process, each making five MPI calls each, has over 10 billion interleavings (schedules). This is what bogs testing tools down -- they do not know which interleavings matter, thus end up missing some interleavings while pursuing others redundantly.

We had a discussion with my friend from mathematics department, Hakan Özadam, about the number of interleavings. Five processes, making five calls each to MPI functions means 25 function calls. For each process, you have to choose 5 function calls. If you number each from 1 to 25, you can have each process choose its functions and move on to the next one. Thus, the number becomes:

C(25/5) * C(20/5) * C(15/5) * C(10/5)

Where C(x/y) = x! / ((x - y)! * y!) The last process simply has to select all the left calls for itself, and thus its number of choices is C(5/5) = 1, only one.

That makes the number quite high. No wonder it is hard to formally verify that a parallel program just doesn't deadlock somewhere and wait indefinitely for an input it is to process (halting problem, anyone?). ISP debugger looks promising on finding certain types of bugs in MPI programs. It seems to have formal framework for following promising interleavings and not checking ones that are sure not to be executed. I wonder how it could be used with Boost libraries, which are the libraries I am using for C++ MPI development.


[thanks to Hakan for his help ]

Anime/Manga and the Japanese

People think anime/manga writers are so imaginative and creative but I can assure you they are not. They just draw how an average Japanese person behaves and reacts.

Semih, on adventures with Kohei.

Ankara Belediye Başkan Adayları

Seçimlere yaklaşık 3 hafta kalmışken adaylar hakkında araştırmalarıma başladım. Genel seçimlerde boş oy attıktan sonra yerel seçimlerde oyumu yararlı bir şekilde değerlendirmek istiyorum. Diğer taraftan "Melih Gökçek olmasın da, kim olursa olsun" şeklinde bir düşünce de aklımdan geçmiyor değil. 7 sene önce Ankara'ya geldiğimde bir Çayyolu metro inşaatından bahsediliyordu, halen bitmedi bu. Yollar delik deşik, özellikle birkaç cadde var ki berbat durumdalar, ne olduğu belli olmayan bir toplu taşıma sistemi, yüksek hava kirliliği, doğalgaz almak için saatlerce kuyrukta bekleyen insanlar, kültür-sanat adına koca bir 0. Bunlar bence Melih Gökçek döneminin sorunları ve yeni gelenle birlikte bazı şeylerin düzeleceği konusunda umudum var (umut fakirin ekmeği misali).

Yaklaşık 7 senedir televizyon izlemiyorum. Bu yüzden seçimle ilgili haberleri genelde internetteki haber sitelerinden veya basılı gazetelerden okuyorum. Dün MHP'nin adayı Mansur Yavaş'in web sitesine girdim ve şöyle bir video gördüm:



Bu videoyu izledikten sonra birkaç dakika gülmekten kendime gelemedim. Oda arkadaşlarına gösterdikten sonra onlarla birlikte gülmeye başladık. Bir gün sonra şimdi soğukkanlı bir şekilde analiz yapabilirim sanırım. Kimsenin hakkını yemek istemem, bu yorumumla kendi fikirlerimi vermek istiyorum.

Öncelikle videonun hedef kitlesi kesinlikle ben değilim. Bilgisayar Mühendisliği okumuş, Yüksek Lisans okumakta olan birisi için videodaki animasyonlar çok komik geliyor. Ankara'ya 8-10 tane üniversite yapılabilir mi? Belediye bütçesi buna izin veriyor mu, ve başka bir tartışma konusu da şu, üniversite kurmak belediyenin görevleri arasında mı? Futuristik, ütopik toplu taşımaya gelince. Hmm, aklıma 30 yıllık ikarus'lar geliyor, ne zaman geleceği belirli olmayan belediye otobüsleri, berbat yollar geliyor. Yani hızlı trenler vs. gösteriliyor ama şu birkaç maddelik basit icraatlar yapılsa hem çok daha ucuza malolacak hem de insanlar çok daha rahatlayacaklar:

  1. Herhalde bir 30 senedir çalışan Macar malı İkarus otobüsleri kaldırılmalı. Halen ODTÜ-Kızılay arasında çalışıyorlar ve çok miktarda egzoz gazı çıkarıyorlar. Acaba belediye otobüsleri egzoz emisyon kontrollerinden muaflar mı? Aynı zamanda gürültü kirliliği de yapıyorlar ve eminim fazla yakıt ta tüketiyorlardır.
  2. EGO Otobüs duraklarına nerede olduğunuzu da gösteren Ankara haritası konmalı, kaç numaralı otobüslerin hangi saatlerde geçtiği ve hangi mahallelerdeki duraklara uğradığı bilgisini gösteren tabelalar asılmalı.
  3. Metro hızlıca genişletilmeli. 7 senedir neden Çayyolu metrosu açılamadı? Bundan kimler rant sağlıyor?

Bu önerdiklerim Mansur Yavaş'ınki gibi ütopik şeyler değiller ama çok daha az paraya çok daha fazla mutluluk sağlayacak şeyler.

Tüm bu söylediklerim aslında video kampanyası üzerinden söyledim. Başkan adayıyla ilgili daha fazla bilgi almak istiyorum ve web sayfasına gidiyorum. Beni böyle bir video karşılıyor :) Bundan sonra acaba siteye girmeli miyim yoksa buna değmez mi diye düşünebilirim. Siteye girdiğimde ise beni başka bir manzara bekliyor. Projeler sayfasında izlediğimiz videoda görülen 8-10 tane üniversiteden haber yok. Ama başka gerçekçi projeler var. Gerçekçi projeler ise asıl beni ilgilendirenler. Engelliler konusundaki ve bilişim konusundaki fikirleri güzel gerçekten. Acaba seçilse ne kadarını gerçekleştirir ve ne kadarını unutur diye düşünmeden geçemiyorum.

Bundan sonra Melih Gökçek'in web sitesine ve ilk olarak engellenen projelerine bakıyorum. İnsan adamın engellenen projelerini görünce engelleyenlere teşekkür edesi geliyor. Uçak otel, Semazen Heykeli, Nasreddin Hoca kentsel dönüşüm projeleri... İnsana acaip gına geliyor, neden Melih Gökçek'in bir sürrealist olduğunu anlamamızı sağlıyor. Melih Gökçek'in projeleri ise Disneyland, Orta Doğu'nun en büyük Hayvanat Bahçesi gibi ilginç (!) projeleri ile bitiremediği metroların bitirilmesi hakkında... Biraz dolaştıktan sonra akıl sağlığımız açısından tarayıcıyı kapatsak iyi olacak.

Murat Karayalçın'ı çok bilmiyorum. Onun projelerine de bakacağım. Aslında amacım Melih Gökçek karşısında kimin kazanma ihtimali varsa ona oy vermek. Oy verecek arkadaşlara tavsiyem adayları iyi tanımaları ve dikkatli bir şekilde oy vermeleri. Sonuçta bu sizin hayatınızı etkileyecek önemli bir olay.

Araştırmalarla ilgili olarak

Google Scholar'ı çok kullanan birisiyim. Tez konusunda araştırma yaparken en çok kullandığım araçlardan oldu kendisi. Scholar yanında ilgili alandaki iyi konferans, dergi, workshop vs. gibi etkinliklerin de ana sayfalarını takip ettim. Belirli bir alanda araştırmalara bakarken insan bazen birkaç sene önceki araştırmalarla çoklukla karşılaşıyor. Bunun nedeni bu araştırma/makalelerin uzun süre önce yayınlandıkları için oldukça fazla atıf almaları ve pek çok web sitesinde bahsedilmeleri. Bu benim gibi araştırmacılar için iyi birşey değil çünkü en son araştırmalar en iyi algoritmalara götürüyor insanı. İnsanlar hızlı bir şekilde eski algoritmaları geliştiriyorlar. Yeni araştırmalara erişmek için benim bulduğum yöntem şu oldu:

  1. Öncelikle "survey", "future directions" gibi genel olarak yeni birşey getirmeyip eski algoritmaları açıklayan makaleleri okumak.
  2. Alanınızla tam ilgili olmasa da yakın olan güncel makaleleri okuyup alanınızdaki makalelere atıf yolu ile ulaşmak. Tüm makalelerde bir "şu anki durum" (current state of art) olduğu için bunlara ulaşmak kolay.
  3. Bundan sonrası size kalmış. Alanınızdaki iyi birkaç makaleye ulaştıktan sonra atıfları izleyerek diğerlerine de ulaşmak olası.
  4. Anahtar kelimeleri de doğru seçmek gerekiyor.

Bugün daha önce görmediğim (veya görüp dikkate almadığım, bilmiyorum) ama bilmem gereken bir makale gördüm. Makaleyi daha önceden bilmem gerekiyordu çünkü benim konumla alakalı. Şimdi bunun tekrarlanmaması için kendime bir not aslında bu yazı. Makale biraz eski olduğu için kaçırmışım. Hımm, bunları unutmamam gerek. Özel sektörde çalışırken de çok faydalı olacaktır.

back of my hand - avucumun içi - elimin tersi

Just noticed that the idiom "know like back of my hand" is in the lyrics of two songs that are in my mp3 player. It is featured in Keane's "Somewhere Only We Know" and Lights' "February Air" songs.

The interesting thing is, we have an idiom which has the exact same meaning, and it is "avucunun içi gibi bilmek". When you translate this literally it means "know like the inside of my palm" :-) When you translate "know like back of my hand" literally to Turkish, it is "elimin tersi gibi bilirim" and it really doesn't make much sense. Back of a hand is not the better part of one's hand in the Turkish culture. I just wanted to share this interesting trivia. It is totally useless so you might as well forget it.

I keep asking my roommate Kohei about Japanese idioms and proverbs. I think idioms and proverbs are really interesting part of one's culture. It shows some parts of a culture that you wouldn't be able to see looking with bare eyes. That's my two cents, anyway (yet another idiom :)).

Just like "Lost in Translation" right? (great movie by the way)

MPI / Grid Hesaplama Üzerine Tez/Araştırma Konuları

Bir arkadaştan "MPI konusunda ne gibi araştırmalar yapabilirim" gibi bir soru geldi. MPI ve Grid hesaplama konusunda günlük sayfamda yazılar yazarak bilgimi başkalarına aktarmaya çalışıyorum. Bu konularda çalışmak isteyen Türklere de aynı zamanda biraz motivasyon vermek için aslında bu, hani daha önce yapanlar da varmış dedirtmek için. Ve sorusu olana bilgim dahilinde tabii ki cevap vermek isterim.

Grid hesaplama ve MPI konusunda aslında oldukça fazla araştırma konusu var bana göre. Örneğin grid konusunda araştırma yapılacaksa Java ile çeşitli servisler yazılabilir. Gridleri yönetmek için kullanılan çeşitli yardımcı programlara, araçlara bakılarak bunlardan fikir edinilebilir. Örneğin vikiden globus toolkit makalesi başlangıç olabilir. Bunlar çok büyük araçlar, özel bir konu seçilip araştırma yapılabilir. Benim aklıma gelen konu mesela "iş ayarlama (scheduling) nasıl geliştirilebilir?". Buna benzer bir alt alanda araştırma yapılabilir.

MPI konusu ise yine çok geniş. MPI ve OpenMP gibi araçlardan hangilerini seçeceksin? MPI seçeceksen hangi sürümünü seçeceksin (OpenMPI, mvapich vs.)? Hangi dilde yazacaksın, bir derleyici sargısı (wrapper) kullanacak mısın? Bu seni sınırlandırır mı? Veya sen kendin mi benzer bir MPI kütüphanesi yazacaksan? MPI senin için bir araçsa bunu ne için kullanacaksın?

Eğer bir MPI kütüphanesi yazmayacaksan ve MPI senin için sadece bir araç olacaksa, bunu ne için kullanacaksın? Bu soru diğer soruların cevaplarını da yönlendirecek aslında. Çalışmak istediğin alanda bir problem bul, bunu MPI ile çözmeye çalışabilirsin. Algoritmayı paralel hale sokman gerekebilir. Veya yeni bir algoritma geliştirmen gerekebilir.

Ben veri madenciliği ile ilgileniyordum, bu yüzden bu alanda bir problem seçtim (sık nesne kümeleri madenciliği) ve bu alanda ne yapabileceğimi araştırdım. Sonra iyi bir algoritma dikkatimi çekti (CLOSET+) ve bunu nasıl paralel bir şekilde MPI ile çalıştırırım diye düşündüm. Algoritmayı değiştirdim ve MPI ile uygulamayı yazdım. Bundan sonra performans testleri kaldı ve başka çeşitli iyileştirmeler.

Yani genel olarak önereceklerim: Hangi alanda çalışmak istediğinize karar verin. Bu herhangi bir Bilgisayar Bilimleri alanındaki bir problemi paralel çözüm uzayına taşımak olabilir veya direk olarak MPI kütüphanesi geliştirmek, bunları servis olarak açmak vs. de olabilir. Sonra bu seçtiğiniz alanla ilgili olarak tüm gelişmeleri takip edin. Bu konuda benim takip ettiğim metod en eski makalelerden başlayarak en güncel makalelelere kadar okumak. Böylece büyük resmi görebilirsiniz (big picture - kelime kelime çeviri oldu, özür dilerim bazen ingilizce düşünüyorum). Ve böylece yeni çözümler için aklınıza fikirler gelebilir. Bundan sonra yapmanız gereken güncel çözümlere yeni neler getirebileceğinizi düşünmek olacak. Bol bol araştırın, problemi farklı bilimlerdeki çözüm uzaylarına yansıtın (özellikle matematikten ağaçlar, çizgeler, çeşitli geometrik 3 boyutlu şekiller) ve daha rahat bir çözüm bulun. Genel olarak çalışmak istediğiniz alandaki en iyi konferansları takip edin, bunlardan çıkan makaleleri okuyun. Alanınızdaki en iyi hocaları, okulları, konferansları takip edin. Siz takip ettikten sonra bence geliştirmek isteyeceğiniz bir problem ortaya mutlaka çıkacaktır.

Bundan sonrası motivasyon işi, benim kötü olduğum bir alan. O yüzden sonrası için kolay gelsin.

Bonus: Türkçe Yüksek Başarımlı Hesaplama Konferanslarından biri Nisan'da ODTÜ'de olacak. Detaylar için BAŞARIM 09 anasayfasına bakabilirsiniz.

Bonus2: Benim de BAŞARIM 09'a kabul edilen bir makalem var. Bunu burada yayınlayacağım, birkaç hafta içinde. BAŞARIM 09'da sunumda yapma planlarım var (eğitim odaklı bir sunum olacak, debugging konusunda olabilir), buna da beklerim.

ntvmsnbc blog sayfası

NTVMSNBC blog sayfasından bir alıntı:

ASP.NET, IIS ve SQL Server gibi en yeni Microsoft teknolojileri üzerine kurulmuş olan [yeni ntvmsnbc.com altyapısı]...

Bunu okuyunca doğal olarak düşündüm. ASP.net, IIS ve MS SQL Server. Ve "en yeni Microsoft teknolojileri". Üzgünüm ama hiç de uyumlu gelmiyor. ASP.net ve IIS'e üniversite 2. sınıfta, yani bundan 5 sene önce zorunlu yaz stajım sırasında bakmış, ODTU IMS'in dinamik bir sayfasını hazırlamıştım. Uydudan gelen veriler işleniyor ve web sayfası güncelleniyordu. MS SQL Server ise birçok kez inceleyip kullandığım, şahsi kanaatimce MySQL ve PostgreSQL'den oldukça geri bir veri tabanı. IIS ise Apache'nin yanında lafını bile edemeyeceğim kadar kötü bir web sunucusu bana göre. Wikipedia'da küçük bir araştırma yapınca ASP.net'in 2002'de, IIS'in en az 10 sene önce, MS SQL Server'ın ise ilk olarak 1989'da (!) çıktığını görebiliyoruz. ntvmsnbc'de çalışanların en yeni teknolojilerden anladıkları bu ise vay hallerine. Gerçi sitenin tüm altyapısını msnbc.com'dan almalarına bakarak ne kadar yetenekli (!) bir yazılım bölümleri olduğunu anlayabiliyoruz. Şimdiden ortaya çıkan Chrome, Firefox ve Opera sorunlarında onlara kolay gelsin diyoruz. Yazılımını kendin üretmeyip Mikisoft'tan alırsan başka ne beklersin ki? Microsoft standartlara en az uyan firma ve bunu kullanıcılarınıza ödetiyor, üstüne de adamlara para veriyorsunuz.

Yazının başında alıntıladığımız blog'ta yazılan cümleler ise bir yazılım bölümünün bir pazarlamacıya emanet edilmesiyle olacakları göstermesi açısından önemli. Keşke ders alınsa.

ntvmsnbc.com haberciliğini tarafsız bulduğum, magazine kaçmayan saçma sapan haberler üretmeyen bir siteydi. Çıkardıkları blog sayfası ise Türkiye'de çoğu şirketin kurumsal blog sayfası yokken güzel bir hareket oldu. Keşke yazılım konusunda da durum böyle olsaydı.

Güzel bir uyarı

peanutbutter:/home/tayfun# aptitude purge mdadm
Reading package lists... Done
Building dependency tree
Reading state information... Done
Reading extended state information
Initializing package states... Done
Reading task descriptions... Done
The following packages will be REMOVED:
mdadm{p}
0 packages upgraded, 0 newly installed, 1 to remove and 3 not upgraded.
Need to get 0B of archives. After unpacking 791kB will be freed.
Do you want to continue? [Y/n/?]
Writing extended state information... Done
(Reading database ... 184934 files and directories currently installed.)
Removing mdadm ...
W: mdadm: I'll update the initramfs, but if you need MD to boot
W: mdadm: with initramfs, you'll be screwed!

Haha, neyse ki boot bölümü raid üzerinde değil.

Adım Adım PostgreSQL'de Tam Metin Arama (Full Text Search)

[Uyarı: Bu uzun dökümandan en fazla yarar sağlamak için rahat bir zamanda okuyunuz. Dökümanın tamamı Tayfun Şen tarafından yazılmıştır. ]


Bu dökümanda PostgreSQL veritabanı üzerinde Türkçe tam metin arama özelliklerinin nasıl kullanılabileceğini anlatacağım. Önce sürüm meselesini bir aradan çıkaralım. Tam metin arama özellikleri son PostgreSQL sürümleri ile birlikte oldukça iyileştirildi. Bundan dolayı ben şu anda son kararlı sürüm olan 8.3.6 sürümünü kullanacağım. İşletim sistemi olarak tercihim Linux, ve dağıtım olarak da Debian öneriyorum. Tabi herhangi bir Linux dağıtımı işinizi görecektir. Eğer zavallı bir Vindoz kullanıcısı iseniz anlatacaklarımı biraz değiştirmeniz gerekebilir (siz en iyisi Linux'a geçin :)).

Eğer yeni bir kurulum yaptıysanız root kullanıcısı olun ve eğer veritabanı sunucusu çalışmıyorsa onu başlatın. Bunun için, örneğin Debian'da,

peanutbutter:/home/tayfun# /etc/init.d/postgresql-8.3 start
Starting PostgreSQL 8.3 database server: main.

demeniz yeterli.

Bundan sonra

peanutbutter:/home/tayfun# su postgres

ile postgres kullanıcısına geçiş yapın. postgres kullanıcısı veritabanı üzerinde tam yetkiye sahip bir yönetici kullanıcısıdır. Bu yönetici kullanıcısı olduktan sonra psql ile veritabanına bağlanabilirsiniz:

postgres@peanutbutter:/home/tayfun$ psql
Welcome to psql 8.3.6, the PostgreSQL interactive terminal.

Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit

Veritabanı yaratmadan önce localization ve i18n hakkında bahsetsem iyi olacak. Eğer Türkçe veri saklayacaksanız veritabanınızın Türkçe karakter kodlamasını kullanması gerekiyor. PostgreSQL, MySQL kadar esnek bir karakter kodlama özelliklerine sahip değil. Bu yüzden her veritabanı kümesi (cluster) için
başlangıçta (initdb ile) verilan LC_COLLATE ve LC_CTYPE gibi önemli yerelleştirme değerleri daha sonra değiştirilemez. PostgreSQL varsayılan olarak
sistem locale değerini kullanıyor. Benimki UTF-8 olduğu için veritabanım da bu kodlamayı kullanıyor. Debian'da locale değerini 'locale' komutu ile öğrenebilirsiniz:

tayfun@peanutbutter:~$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=


Şimdi bir veritabanı yaratalım ve bağlanalım:

postgres=# create database deneme;
postgres=# \c deneme

Burada durup PostgreSQL'in bize tam metin arama için sağladığı güzelliklere değinelim. Eğer PostgreSQL dökümanlarını okursanız tsvector ve tsquery gibi iki veri yapısını sıklıkla duyacaksınız. Bunlardan tsvector dökümanınızı arama yapmaya uygun halde tutar, tsquery ise arama yaparken kullandığınız sorgular için tasarlanmıştır.

Şimdi tam metin için örnek bir veritabanı tablosu oluşturalım. Bu tabloya ntvmsnbc'deki bazı haber metinlerini ekleyeceğim. Tablomuzda tipik olarak başlık, özet, anahtar kelimeler, tam metin, yazar gibi alanlar olacak.

deneme=# create table metin (baslik varchar(100), ozet text, anahtar_kelimeler varchar(200), tam_yazi text, yazar varchar(200));

Şimdi biraz veri yükleyelim:

deneme=# insert into metin values ('İhracat yüzde 35 geriledi', 'İhracat Şubat ayında yüzde 35 düşerek 6.9 milyar dolar olarak gerçekleşti. Otomotiv ihracatında yüzde 55 azalma yaşandı.', 'ihracat, otomotiv, gerileme, kriz', 'Krizin etkisiyle pazarlardaki daralmayla ihracatta kan kaybı devam ediyor. Türkiye İhracatçılar Meclisi (TİM) verilerine göre Şubat ayında ihracat önceki yılın aynı dönemine göre yüzde 35 düşüşle 6.9 milyar dolar oldu. Ocak-Şubat döneminde ihracat yüzde 31''lik azalışla 13.9 milyar dolar olarak gerçekleşti. Son 12 aylık ihracat verilerinde ise yüzde 8.1 artış yaşandı. Böylece toplam yıllık ihracat 121.7 milyar dolar oldu. Türkiye İhracatçılar Meclisi (TİM) Başkanı Mehmet Büyükekşi, Şubat ayı ihracat rakamlarını açıklamak için Uludağ İhracatçı Birlikleri''nde düzenlediği basın toplantısında, otomotiv sektörünün geçen ay 1 milyar 98 milyon dolarlık ihracat gerçekleştirerek, dış satımda sektörler arasında liderliğini sürdürdüğünü ve 1 milyar dolar ihracat yapan tek sektör olduğunu belirtti. Otomotivi 984 milyon dolar ile demir - çelik ve 967 milyon dolar ile hazır giyim ve konfeksiyon sektörlerinin takip ettiğini anlatan Büyükekşi, tarım ve hayvancılık grubu sektörlerinin ihracatının ise Şubat ayında yüzde 3.31 gerilerken, toplam ihracat içinde yüzde 14.39''luk pay aldığını bildirdi.', 'Ajanslar');


deneme=# insert into metin values ('Şahin: Sözlerim maksadını aştı', 'Adalet Bakanı Şahin, "Hükümetle zıtlaşan yerel yönetimler her projelerini Ankara’dan geçiremiyor" sözleri için "Yanlış ve maksadını aşan bir ifadedir" dedi.', 'şahin, adalet bakanı, şantaj, rant', 'TBMM''de konuşan muhalefet milletvekilleri Adalet Bakanı Mehmet Ali Şahin''in hafta sonu Antalya''da söylediği "Hükümetimizle kavga eden, zıtlaşan yerel yönetimler her projelerini Ankara’dan geçiremiyor. Maalesef bu Türkiye’nin gerçeği" sözlerini eleştirdi. Kürsüye gelen Adalet Bakanı Şahin, eleştirileri anlayışla karşıladığını belirtti. Adalet Bakanı Şahin, şöyle konuştu: "Orada yaptığım konuşmalarda genel olarak vermek istediğim mesaj şuydu; bir yerel yönetimin, bir belediyenin, bir belediye başkanın, başka belediyelerin veya merkezi yönetimin yardımı olmadan çözemeyeceği bir takım sorunları vardır. O nedenle belediye başkanı olarak seçeceğiniz arkadaşın, diğer belediyelerle, diğer kuruluşlarla diyaloğu devam ettirecek, onların da yardımını alabilecek, onlarla birlikte çalışabilecek kapasitede arkadaşlar olması gerektiğini ifade ettim. Bunu söylerken, şu partiden, bu partiden ayrımı yapmadım. Ama Gazipaşa''da ''Eğer seçeceğiniz belediye başkanı bizim partiden olursa memnun olurum'' anlamına gelen bir ifade kullandım. Yerel yöneticilerin büyükşehir belediyesi ve merkezi hükümetle de uyum halinde, diyalog halinde olmasının yararlı olacağını düşündüm. Beni buraya getiren neydi? Ben Antalya milletvekiliyim ve kabinede görev yapıyorum. Antalya''da bazı ilçe ve beldeleri ziyaret ediyorum. Mesela bazı ilçeler var ki, henüz altyapıları, kanalizasyon sorunları bile büyük ölçüde çözülmedi. Ben bizim partiden olmayan bu belediyelerin bulunduğu yerlere gittiğimde mevcut belediye başkanı arkadaşlarımla bir diyalog kurayım, acaba birlikte burada bir çözüm üretebilir miyiz'' dediğimde, bazı ilçeler var ki bu belediye başkanlarıyla ben maalesef 3-4 yıldır tanışma şerefine nail olamadım. Ben bunu bazı yerlerde eleştirdim. ''Keşke bu belediye başkanı arkadaşlarımla diyalog kurabilsek, başka partiden olabilir ama belki buradaki sorunlara birlikte çözüm üretebiliriz'' diye bir takım konuşmalar da yaptım."', 'ajanslar');


deneme=# insert into metin values ('Gül dava açtı, Arıtman ısrarlı', 'Cumhurbaşkanı Gül ve CHP’li Arıtman arasındaki tartışma yeni bir boyut kazandı. Cumhurbaşkanı tazminat davası açtı, Arıtman ısrarlı açıklamalarını sürdürdü: Nüfus kütükleri Türk olduğunu kanıtlayamaz.', 'canan arıtman, gül, saçmalıklar, politikacıların zeka seviyesi', 'Cumhurbaşkanı Gül, “Hakkımda bir yalan yaymak istiyorlar” iddiasıyla, kendisi için “Annesinin kökenine bir bakın” diyen CHP milletvekili Canan Arıtman hakkında 1 YTL''lik manevi tazminat davası açtı. Gül''ün etnik kökenleri konusunda açıklama yapmasına sebep olan iddiaları ileri süren Arıtman ise, bugün de “Nüfus kütüklerinden köken belli olmaz” diyerek ısrarlı tavrını sürdürdü. CHP İzmir Milletvekili Canan Arıtman, 1915 olayları için başlatılan “Özür diliyorum” kampanyasına tepki göstermediği gerekçesiyle Cumhurbaşkanı Abdullah Gül''ü eleştirmiş, “Tabii ki destekler, annesinin kökenine bir bakın” demişti.

Arıtman''ın bu açıklamasından sonra önce sessiz kalan Cumhurbaşkanı Gül, pazar günü yazılı açıklama yaparak kendisi hakkında yayılmak istenen bir yalanı düzeltmek istediğini belirtti. Gül, açıklamasında “Kayseri’nin yerlisi olan annem tarafından Satoğlu, babam tarafından Gül sülalelerinden gelen ailemizin yüzyıllara uzanan kayıtlı geçmişi Müslüman ve Türk''tür. Buna ailemizin geçmişten günümüze birlikte titizlikle işlenen soy ağacımız, mevcut resmi nüfus kütükleri ve gelmiş geçmiş Kayseri''li hemşehrilerimiz şahittir” ifadesini kullanmıştı.', 'NTV-MSNBC');

Şimdi tablomuzda üç tane satır var. Verilerimizi de eklediğimize göre bu tabloda tam metin arama nasıl yapabiliriz? Aslında çok zor birşey değil. Örnek tablomuzdaki tam yazı alanınında sorgumuzu şöyle gerçekleştirebiliriz:

deneme=# select baslik from metin where to_tsvector(tam_yazi) @@ to_tsquery('söz');
baslik
--------------------------------
Şahin: Sözlerim maksadını aştı
(1 row)

deneme=# select baslik from metin where to_tsvector(tam_yazi) @@ to_tsquery('kütük');
baslik
--------------------------------
Gül dava açtı, Arıtman ısrarlı
(1 row)

Bu iki sorguda da tam_yazi alanı to_tsvector fonksiyonu yardımı ile tsvector haline ve sorgu için kullanacağımız kelimeler ('söz' ve 'kütük') to_tsquery fonksiyonu ile tsquery haline getiriliyor. Bundan sonra @@ operatörü ile sorgumuzu çalıştırabiliyoruz. Sorgularımızı gerçekleştirirken boolean operatörleri kullanabiliriz, &, | ve ! sembolleri yardımı ile. Örnek bir sorgu şöyle olabilir:

deneme=# select baslik from metin where to_tsvector(tam_yazi) @@ to_tsquery('türkiye');
baslik
--------------------------------
İhracat yüzde 35 geriledi
Şahin: Sözlerim maksadını aştı
(2 rows)

ama

deneme=# select baslik from metin where to_tsvector(tam_yazi) @@ to_tsquery('türkiye & çözüm');
baslik
--------------------------------
Şahin: Sözlerim maksadını aştı
(1 row)

ts_vector ve ts_query veri yapılarının nasıl tutulduğunu görmek ister misiniz? Bunu şu şekilde görebilirsiniz:

# select to_tsvector(tam_yazi) from metin where baslik='Şahin: Sözlerim maksadını aştı';

'3':211 'e':19 'p':105,219 'u':138 '-4':212 'be':146 'et':104 'he':170 'in':11 'mi':200 'ne':149 'on':92,96 'so':13 'ali':9 'ayr':111 'ben':150,178,209,218 'bil':174 'bir':58,61,63,74,127,191,197,241 'biz':120,179 'dan':26 'haf':12 'hal':1
...
...
...

Bu SQL sorgusunun sonucu olarak köklerine ayrılmış kelimeleri ve her birinin dökümandaki yerini göreceksiniz. Örnek olarak 'bir' kelimesi 58, 61, 63. sırada görülmüş (ve daha birçok yerde).

Bunu daha basit şekilde de deneyebiliriz:

deneme=# select to_tsvector('deneme cümlemiz bu olsun. olsun!');
to_tsvector
---------------------------
'ol':4,5 'dene':1 'cümle':2
(1 row)

Burada da görüldüğü gibi 'deneme' ve 'olsun' kelimelerimiz köklerine ayrıldı.

ts_query yapısını da benzer bir şekilde deneyebiliriz.

Dikkatli okuyucular az önce tabloya karşı yaptığımız sorgularda tam yazı alanlarının canlı olarak tsvector'e çevrildiğini farketmişlerdir. tsvector'ün yapısı incelendiğinde bunun maliyetli bir işlem olduğu görülebilir. Peki bunu nasıl daha kolay ve verimli bir hale sokabiliriz?

Bunun aslında iki yolu var. İlk yöntem ile sadece bir index tanımlaması yaparak aramalarımızı hızlandırabiliriz. Bunun için index'imizi to_tsvector(tam_yazi) olarak tanımlamamız gerekiyor. İkinci yöntemde ise tabloya bir alan ekleyip o alana tsvector'leri doldurabiliriz. Bu yöntemleri biraz daha detaylı inceleyelim.

İkinci yöntemimizden başlarsak, fazladan bir alan ile tsvector yapılarımızı saklamak maliyeti yüksek bir yöntem. Bunun nedeni tablonuzu büyütmesi ve bu alanın güncel tutulması için gerekecek trigger benzeri yapılarının verimlilik sorunları. Yine de bu yöntemi uygulamak istersek şu şekilde yapabiliriz:

Öncelikle trigger yazmamız gerekiyor. Bir dosya yaratın ve içine şunları yazın:

CREATE OR REPLACE FUNCTION norm_text (
text_to_normalize text
) RETURNS text AS $$
DECLARE
normalized_string text;
BEGIN
select translate(text_to_normalize, 'çğıöşüÇĞÖŞÜİ', 'cgiosuCGOSUI')
into normalized_string;

return normalized_string;

END;
$$ LANGUAGE plpgsql IMMUTABLE;


CREATE OR REPLACE FUNCTION lexeme_trigger ()
RETURNS trigger AS $$
begin
new.lexemes :=
setweight(to_tsvector('turkish', coalesce(norm_text(new.baslik), '')), 'A'
) ||
setweight(to_tsvector('turkish', coalesce(norm_text(new.anahtar_kelimeler)
, '')), 'B') ||
setweight(to_tsvector('turkish', coalesce(norm_text(new.ozet), '')), 'C')
||
setweight(to_tsvector('turkish', coalesce(norm_text(new.tam_yazi), '')), '
D');
return new;
end
$$ LANGUAGE plpgsql;

(İleride değinilecek ama burada bahsetmekte fayda var: turkish ile köklere ayırma yapılacaktır, eger yanlış işler yapıyorsa bu ayırma işlemi, sözlük zinciri yaratılabilir).

Burada tek uyguladığımız sadece bir trigger değil, tam metin aramanın başka bir özelliğinden de yararlanıyoruz. Bu özellik ağırlıklandırma. setweight fonksiyonu ile tablodaki alanlara ağırlıklar veriyoruz. A harfinden D'ye doğru ağırlık azalıyor. En önemli alan olan başlık bilgisi en fazla ağırlığa sahip, bu sayede sorgunun birden fazla satırda eşleniği varsa eşlenen alanların ağırlığına göre bir sıralama yapılacak.

Bunun dışında ilk tanımlanan fonksiyon norm_text, adından da anlaşılacağı gibi yazı normalisation yapıyor. PostgreSQL'de MySQL gibi gelişmiş collation seçenekleri yok, accent insensitive eşleme yapabilmek için kendi fonksiyonumuzu yazmamız gerekiyor. norm_text bunu yapıyor, Türkçe karakterleri değiştiriyor. Bu sayede kırmızı aradığımızda kirmizi'lari da bulacağız. Eğer bu türden bir özelliğe ihtiyacımız yoksa bu fonksiyonu ve kullanıldığı yerleri kaldırabiliriz. Accent insensitive arama yapmak istiyorsak hem tsvector oluştururken, hem de tsquery oluştururken bu fonksiyonu kullanmak durumundayız.

Bu trigger ve normalisation fonksiyonunun tanımının yapıldığı dosyayı PostgreSQL'e vermemiz gerekiyor. Ama öncesinde bu trigger'ın yazıldığı dilin (plpgsql) etkin olması gerek:

deneme=# create LANGUAGE plpgsql;

Şimdi fonksiyonumuzun bulunduğu dosyayı verebiliriz:

deneme=> \i ~tayfun/yonca/norm_text.sql
CREATE FUNCTION

Artık tsvector'lerin tutulacağı alanı oluşturabilir

deneme=> alter table metin add column lexemes tsvector;

ve trigger'ı yaratabiliriz:

deneme=> CREATE TRIGGER lexemeupdate BEFORE INSERT OR UPDATE ON metin FOR EACH ROW EXECUTE PROCEDURE lexeme_trigger();

Artık her metin eklemesinde lexeme kolonu tsvector ile güncellenecektir. Bundan sonra bu alanı kullanarak tam metin arama yapabiliriz. Eski satırlarımızı güncellemek için:

deneme=# update metin set lexemes =
deneme-# setweight(to_tsvector('turkish', coalesce(norm_text(baslik), '')), 'A') ||
deneme-# setweight(to_tsvector('turkish', coalesce(norm_text(anahtar_kelimeler), '')), 'B') ||
deneme-# setweight(to_tsvector('turkish', coalesce(norm_text(ozet), '')), 'C') ||
deneme-# setweight(to_tsvector('turkish', coalesce(norm_text(tam_yazi), '')), 'D');
UPDATE 3

Eski veri de arama yapmaya uygun hale getirildiğine göre, sorgulara başlayabiliriz:

deneme=# select baslik from metin where lexemes @@ to_tsquery('sah');
baslik
--------------------------------
Şahin: Sözlerim maksadını aştı
(1 row)

Eğer veritabanındaki lexemes alanı incelenirse kelimelerin köklerine ayrıştırılmış oldukları görünür. Bundan başka kelimelerin (lexeme'lerin) yanında hangi bölümde (A, B, C ve D) oldukları da belirtilmiştir. Türkçe köklere ayırmanın bazı gariplikleri vardır:

deneme=# select to_tsvector('turkish', 'cümle');
to_tsvector
-------------
'ç':1
(1 row)

Bundan dolayı 'ç' harfi arandığında içinde 'cümle' kelimesi geçen satırlar getirilecektir. Belki biraz daha az garip örnekler:

deneme=# select to_tsquery('turkish', 'kelime');
to_tsquery
------------
'kel'
(1 row)

deneme=# select to_tsquery('turkish', 'araba');
to_tsquery
------------
'arap'
(1 row)

Son örnekte görüldüğü üzere 'arap' kelimesi arandığında içinde 'araba' geçen satırlar da eşlenecektir. Varsayılan olarak Türkçe arama yapılması için:

deneme=> set default_text_search_config=turkish;

komutu kullanılabilir.

tsvector yapılarında lexeme yanında bulunan pozisyon bilgileri "proximity ranking" sıralaması için kullanılmaktadır.

Dillerde aramaya katmanın pek mantıklı olmadığı kelimelere stop words denmektedir (Türkçe'de 'bu', 'şu', 've', 'mesela' gibi..) Bu kelimeler /usr/share/postgresql/8.3/tsearch_data/ benzeri bir klasörde bulunmaktadır, buraya aramada kullanılmasını istemediğiniz yeni kelimeleri ekleyebilirsiniz.

Eğer Türkçe arama yapmak istemiyorsanız, yeni bir sözlük dizisi oluşturmanız gerekir. Bu konuya daha sonra tekrar değineceğim.

Tam metin arama yollarından ikincisi, yani ayrı bir tablo alanında tsvector bilgilerini tutma tekniğini gördük. Şimdi anlatacağımız bir numaralı teknik ise direk index oluşturmaktan geçiyor:

deneme=# CREATE INDEX metin_idx1 ON metin USING gin((
setweight(to_tsvector('turkish', coalesce(norm_text(baslik), '')), 'A') ||
setweight(to_tsvector('turkish', coalesce(norm_text(anahtar_kelimeler), '')), 'B') ||
setweight(to_tsvector('turkish', coalesce(norm_text(ozet), '')), 'C') ||
setweight(to_tsvector('turkish', coalesce(norm_text(tam_yazi), '')), 'D')));

CREATE INDEX

Artık baslik, anahtar kelimeler, ozet ve tam_yazi alanları üzerinde tanımlı bir indeksleme mekanizması devrededir. Bu sayede büyük veritabanları için devasa verimlilik artışları mümkündür. Esasında önceki teknikte verilen fazladan kolon üzerinde de index tanımı mümkündür, bunun yanında tek tek diğer kolonlar üzerinde index oluşturmak da bu kolonlarda tam metin arama yapılacaksa faydalı olabilir:

CREATE INDEX metin_baslik_idx ON metin USING gin(
to_tsvector('basit', norm_text(baslik)));

CREATE INDEX metin_ozet_idx ON metin USING gin(
to_tsvector('basit', norm_text(ozet)));

CREATE INDEX metin_anahtarlar_idx ON metin USING gin(
to_tsvector('basit', norm_text(anahtar_kelimeler)));

CREATE INDEX metin_tam_yazi_idx ON metin USING gin(
to_tsvector('basit', norm_text(tam_yazi)));

CREATE INDEX metin_yazar_idx ON metin USING gin(
to_tsvector('basit', norm_text(yazar)));

Burada dikkat edilirse 'basit' isimli bir sözlük zincirini kullandık, 'turkish' yerine. Bunu daha tanımlamadığımız için hata almış olabilirsiniz. Eğer Türkçe eklere ayırma gibi özellikleri istemiyorsanız yeni bir basit sözlük zinciri oluşturmanız faydalı olur:

deneme=> CREATE TEXT SEARCH DICTIONARY public.simple_turk (
TEMPLATE = pg_catalog.simple,
STOPWORDS = turkish
);

deneme=> CREATE TEXT SEARCH CONFIGURATION public.basit (COPY = pg_catalog.turkish);

deneme=> alter text search configuration basit alter mapping for asciihword, asciiword, hword, hword_asciipart, hword_part, word with simple_turk;

Tüm bunları yaptıktan sonra basit isimli yeni bir sözlük zincirimiz yaratıldı. Bu sözlük kümesi pek bir kök ayrımı yapmıyor, bunu şu şekilde test edebiliriz:

deneme=# SELECT * FROM ts_debug('public.basit', 'fdeenem tayfun türkçe mi birşey üğöç');
alias | description | token | dictionaries | dictionary | lexemes
-----------+-------------------+---------+---------------+-------------+-----------
asciiword | Word, all ASCII | fdeenem | {simple_dict} | simple_dict | {fdeenem}
blank | Space symbols | | {} | |
asciiword | Word, all ASCII | tayfun | {simple_dict} | simple_dict | {tayfun}
blank | Space symbols | | {} | |
word | Word, all letters | türkçe | {simple_dict} | simple_dict | {türkçe}
blank | Space symbols | | {} | |
asciiword | Word, all ASCII | mi | {simple_dict} | simple_dict | {mi}
blank | Space symbols | | {} | |
word | Word, all letters | birşey | {simple_dict} | simple_dict | {}
blank | Space symbols | | {} | |
word | Word, all letters | üğöç | {simple_dict} | simple_dict | {üğöç}
(11 rows)

Bundan sonra şu şekilde daha karmaşık aramalar yapabiliriz:

deneme=> select * from metin where to_tsvector('basit', norm_text(tam_yazi)) @@ to_tsquery('basit', norm_text('ab')) AND to_tsvector('basit', norm_text(anahtar_kelimeler)) @@ to_tsquery('basit', norm_text('politikacı'));

Her alanda belirli kelimeleri bulmak bu şekilde daha hızlı ve kolay olacaktır çünkü her alanda index'imiz vardır.


Eğer varsayılan tam metin arama dili olarak Türkçe'yi kullanmak istiyorsanız ('turkish' olarak verilen argüman yerine) bu ayarı direk veritabananı için düzenleyebilirsiniz:

deneme=# alter database deneme set default_text_search_config = turkish;

EXPLAIN ve EXPLAIN ANALYZE ile Testler


Explain komutunu kullanarak bir sql sorgusunun tahmini nasıl çalıştırılacağını görebilirsiniz. 'explain analyze' ise sorguyu gerçekten çalıştırır ve sonuçları verir. Sorgu planlayıcısına (query planner) komut vererek indexler varken sequential scan yapmamasını sağlayabilirsiniz:

Explain kullandığınızda index yaratmamıza rağmen halen seq. scan (sıralı tarama) yapıldığını görüp şaşırabilirsiniz:

deneme=# explain select * from metin where to_tsvector('basit', norm_text(tam_yazi)) @@ to_tsquery('basit', norm_text('ab'));
QUERY PLAN
---------------------------------------------------------------------------------------
Seq Scan on metin (cost=0.00..2.79 rows=1 width=336)
Filter: (to_tsvector('basit'::regconfig, norm_text(tam_yazi)) @@ '''ab'''::tsquery)
(2 rows)

İşin aslı şu ki, sorgu planlayıcımız tabloda az miktarda veri olduğunu görüyor ve index kullanmak (ağaç yapıları ve hash kodlaması) yerine sıralı bir şekilde teker teker kontrol etmenin daha hızlı olacağını düşünüyor. Aslında yanılıyor da sayılmaz, bizim veritabanımız çok küçük, adam hash hesaplayana veya ağaç (B-tree?) ile uğraşana kadar hepsini teker teker kontrol edebilir. Biz testlerde bunun böyle olmamasını istiyoruz. Bunun için manuel olarak sıralı tarama özelliğini kapatabiliriz:

deneme=> set enable_seqscan = false ;
deneme=> show enable_seqscan;

Bu komut ile sorgu planlayıcının elinden sıralı tarama aracını almış oluyoruz, o da artık diğer alternatiflere bakmak zorunda. Yukarıda Seq. Scan yapılan sorguyu aynen tekrarladığımızda:

deneme=# set enable_seqscan = false;
SET
deneme=# explain select * from metin where to_tsvector('basit', norm_text(tam_yazi)) @@ to_tsquery('basit', norm_text('ab'));
QUERY PLAN
-------------------------------------------------------------------------------------------
Index Scan using metin_tam_yazi_idx on metin (cost=0.25..8.52 rows=1 width=336)
Index Cond: (to_tsvector('basit'::regconfig, norm_text(tam_yazi)) @@ '''ab'''::tsquery)
(2 rows)

Süper, index'imiz veritabanımız büyüdükçe sorgu planlayıcı tarafından daha da kullanılacak.


Sıralama ve İşaretlemeler



Peki herhangi bir aramada sıralamayı nasıl değiştirebiliriz? Ve hangi alanların eşleştiğiini nasıl öğreniriz?

Sıralama konusu basitce şöyle:

deneme=# select baslik, ts_rank(lexemes, to_tsquery('basit', 'Turkiye')) as rank from metin where lexemes @@ to_tsquery('basit', 'Turkiye');
baslik | rank
---------------------------+-----------
İhracat yüzde 35 geriledi | 0.0759909
(1 row)

Burada tek yapılan ts_rank fonksiyonu ile tsvector ve aranılan sorgu kelimeleri arasındaki ilişki puanını seçmek. Bu basit örnek kullanılarak puana göre sıralama yapılabilir.

Bunun dışında bir web sayfasında ilişki kurulan veri ile sorgunun nerelerde eşleştiğini işaretlemek sıkça kullanılan bir yöntem. Örneğin google, sorgularında eşlenen kelimeleri kalın harflerle veya sarı arka planda gösterebiliyor. Bunu PostgreSQL de -biraz sınırlı olsa da- yapabiliyor. ts_headline fonksiyonu bu işe yarıyor:

deneme=# select ts_headline('basit', tam_yazi, to_tsquery('basit', 'mesela')) from metin where lexemes @@ to_tsquery('basit', 'mesela');
ts_headline
---------------------------------------------------------------------------------------------------------------------
Mesela bazı ilçeler var ki, henüz altyapıları, kanalizasyon sorunları bile büyük ölçüde çözülmedi. Ben bizim
(1 row)

ts_headline fonksiyonunun çok ilginç özellikleri var. Varsayılan olarak <b> ile etiketlenen eşleşmeyi değiştirebilirsiniz, kaç tane kelimenin verileceğini ayarlayabilirsiniz.

ts_headline fonksiyonu arka planda tsvector verisini kullanMIyor. tsvector'de pozisyon da tutulduğu için insan aksini düşünebilir ama ts_headline her seferinde baştan eşleşme yerlerini buluyor. Bu yüzden çok hızlı olduğu söylenemez. Eğer sizin istediğiniz esneklikte değilse başka bir yöntem ile (PHP?) işaretleme sağlanabilir.

Sınırlamalar


tsvector veri yapısının büyüklüğü en fazla 1 MB olmalı ve tsvector'deki pozisyon bilgisi 16383'den büyük olmamalı, yani bir dökümanda en fazla 16383 tane kelime bulunabilir.

Eğer PostgreSQL'in tam metin arama yetenekleri sizi kesmezse daha esnek olan Sphinx'i deneyebilirsiniz.


Kolay gelsin.



Referanslar:
PostgreSQL resmi dökümanları, örneğin: http://www.postgresql.org/docs/8.3/interactive/textsearch-intro.html
Tam metin sorgu bölümü için: http://www.postgresql.org/docs/8.3/interactive/textsearch.html

Copyright © 2008
Design Disease - Blog and Web - Dilectio Blogger Template