• Cum. May 3rd, 2024

Arif GÖKÇE

Senior Software Engineer

Bu makalemizde, Sql sunucu üzerindeki tablolarda text tabanlı arama işlemlerinin, Full-Text Searching (Tüm Metinde Arama) servisi yardımıyla nasıl gerçekleştirildiğini incelemeye çalışacağız. Konunun pekişmesi açısından basit bir web uygulması ile de bu hizmeti kullanıp text tabanlı arama işlemlerini irdelemeye çalışacağız. Özellikle dikkatinizi çekmiştir ki, internette yer alan pek çok arama motoru aradığımız kelimelerin geçtiği web sayfalarını bulup bize getirir. Çoğunlukla arama motoruna kayıtlı web sayfasının içeriğinde yapılan text tabanlı aramalar da Full-Text Searching (Tüm Metinde Arama) hizmetinden faydalanılır. Bu tip bir arama genellikle alanları içerisinde çok geniş text tabanlı içeriğe sahip olan tablolar üzerinde yapılmaktadır. Sql sunucusu, 7.0 versiyonundan itibaren bu hizmeti vermeye başlamıştır. Elbetteki arama işleminin gerçekleştirilebilmesi için Full-Text Searching (Tüm Metinde Arama) servisinin Sql sunucusunda yüklü olması gerekmektedir. Dilerseniz hiç vakit kaybetmeden bir tablo için Full-Text Index’ in nasıl oluşturulacağına kısaca bakalım. Öncelikle, Full-Text Indeksleme yapacağımız tablonun adına enterprise manager’ dan sağ tıklayoruz ve aşağıdaki gibi Define Full-Text Indexing On a Table’ ı seçiyoruz. Bu işleme başlamadan önce tablomuzda bir primary key alan olması gerektiğinide belirtelim. Nitekim indeksleme işlemlerinde bu alan, sonuçların döndürülmesinde anahtar alan olarak kullanılmaktadır.

Bu işlemi takiben, karşımıza çıkan sihirbazdaki adımları sırasıyla takip ederek ilerliyoruz. Daha önce belirttiğim gibi, öncelikle tablomuzdaki birincil alan için bir indeks seçimi yapılıyor.

Bu işlemin ardından, hangi kolonlarda arama yapılacağını belirtiyoruz. Full-Text aramalar genellikle uzun metin verilerinin tutulduğu alanlarda kullanılır. Örneğin, tablomuzdaki “Icerik” alanı, makalelere ait HTML içeriğini barındıran “ntext” veri tipine sahiptir. Bu nedenle, sadece karakter veya binary içerikli aramalara izin veren alanlar burada görüntülenir. Primary key gibi alanlar veya tarih formatındaki alanlar burada görünmez. Çünkü bu tür alanlarda Full-Text Indexing işlemi anlamlı olmayabilir. Artık seçtiğimiz alanlar üzerinde Full-Text Searching (Tüm Metinde Arama) işlemi gerçekleştirebiliriz.

Sıradaki adımda, arama işlemi için gerekli katalog tanımlanır. Full-Text Indexing aslında bir katalogda tutulmaktadır. Dolayısıyla, gerçekleştireceğimiz arama işlemleri de bu katalogu kullanacaktır. Kataloglar genellikle varsayılan olarak “d:\Program Files\Microsoft SQL Server\MSSQL\ftdata” fiziksel adresinde tutulur.

Daha sonraki adımlarda ise, kataloğun belirli periyotlarda tekrar doldurulmasını sağlayacak Schedule (Takvim) ayarlarını da yapabiliriz. Bu ve izleyen adımları geçtikten sonra tek yapmamız gereken kataloğun doldurulması işlemidir. Bunun için, iki seçeneğimiz var. Birisi “Start Full Population”. Bu seçenek ile katalog baştan itibaren indekslenerek oluşturulur. Bir diğer seçeneğimiz ise “Start Incremental Population” dır. Bu seçenek sayesinde sadece tablonun eski hali ile yeni hali arasındaki farklar indeksleme işlemine katılarak katalog güncellenir. Bu daha önceden kataloglanmış indeksler için geçerli bir seçenektir. Şu anda biz kataloğu yeni oluşturduğumuzdan “Start Full Population” seçeneğini kullanacağız.

Bu işlemleri tamamladıktan sonra, veritabanında yer alan “Full-Text Catalog” sekmesinde, tanımladığımız katalogun oluşturulduğunu görebiliriz.

Eğer tabloda yapılan güncellemelerden sonra katalogun otomatik olarak yenilenmesini istiyorsak, Change Tracking özelliğini aktif hale getirmemiz gerekmektedir. Aynı zamanda katalog güncellemelerinin arka planda yapılmasını sağlamak için Update Index in Background seçeneğini de aktif hale getirmeliyiz. Bu sayede, tabloya yeni satırlar eklediğimizde, Full-Text Searching (Tüm Metinde Arama) işlemi için kullanılan katalog bilgileri otomatik olarak güncellenmiş olacaktır.

T-SQL’de Full-Text Searching (Tüm Metinde Arama) işlemini gerçekleştirmek için FREETEXT ve FREETEXTTABLE anahtar sözcüklerini kullanabiliriz. Bu anahtar sözcüklerin prototipleri aşağıdaki gibidir:

  1. FREETEXT: Belirli bir alan üzerinde belirtilen anahtar kelimeyi arar ve eşleşen sonuçları döndürür. Örneğin:
SELECT * FROM myTable WHERE FREETEXT(myColumn, 'aranacak kelime')

Bu sorgu, myTable adlı tablonun myColumn adlı alanında ‘aranacak kelime’ anahtar kelimesini arar ve eşleşen sonuçları döndürür.

  1. FREETEXTTABLE: Belirli bir tablo üzerinde belirtilen anahtar kelimeyi arar ve sonuçları farklı bir tablo formatında döndürür. Örneğin:
SELECT Key, Rank FROM FREETEXTTABLE(myTable, myColumn, 'aranacak kelime')

Bu sorgu, myTable adlı tablo üzerinde myColumn adlı alanı kullanarak ‘aranacak kelime’ anahtar kelimesini arar ve sonuçları Rank ve Key alanlarını içeren bir tablo formatında döndürür. Key alanı, arama işleminin yapıldığı katalog oluşturulurken kullanılan primary key değerlerini alırken, Rank alanı aranan kelimelerin bulunduğu satırlar arasında bir derecelendirme yapmamıza imkan tanır.

“Artık işin içine biraz eğlence katıyoruz! FREETEXTTABLE anahtar sözcüğü sayesinde, aradığımız kelimenin en çok geçtiği satırlardan başlayarak az geçtiği satırlara doğru bir sıralama elde edebiliriz. Veya aradığımız kelimenin en iyi eşleştirildiği alanlardan en az eşleştirildiği alanlara doğru bir sıralama da yapabiliriz. Böylece, verilerimizi ciddiyetini bozmadan, biraz eğlenceli bir şekilde sıralayabiliriz. Rank alanı sayesinde, veritabanımızda ne kadar eğlence olduğunu keşfetmek için harika bir yol!”

İlk olarak Query Analyzer yardımıyla bu sorguların çalıştırılmasını inceleyelim.

Burada görüldüğü gibi, FREETEXT anahtar sözcüğü, Icerik isimli alanda overload anahtar kelimesinin geçtiği satırların olduğu sonuç kümesini elde etmemizi sağlamıştır.

FreeTextTable anahtar sözcüğünün kullanımı, Join tekniği ile birleştirildiğinde arama sonuçlarını daha da güçlü ve karmaşık hale getirir. Join tekniği, arama işlemi sonucu elde edilen tabloyu, aramanın yapıldığı tablo ile birleştirmek amacıyla kullanılır. Bu işlemde, arama sonuçlarının KEY alanı ile Makale tablosunun primary key alanı olan ID alanları eşleştirilir. RANK alanına göre tersten sıralanmış bir veri kümesi elde edilir. Bu küme, aranan kelimenin en uygun şekilde eşleştirildiği satırları en üste getirir.

Şimdi, Full-Text Searching (Tüm Metinde Arama) işlemini bir asp.net uygulamasında kullanalım. Bu uygulamada, kullanıcının girdiği kelimeyi makalelerin içeriğinde arayacak ve bulunan sonuçları bir DataGrid kontrolünde göstereceğiz. Güvenlik nedenleriyle Sql Injection saldırılarına karşı önlem almak için bir Stored Procedure kullanacağız. Öncelikle, aşağıdaki gibi bir Stored Procedure oluşturalım:

CREATE PROCEDURE dbo.sp_AraBul
(
      @Aranan nvarchar(255)
)
AS
 
SELECT A.*,M.Konu,M.Tarih,M.[ID] FROM Makale AS M
INNER JOIN
FREETEXTTABLE(Makale,Icerik,@Aranan) AS A
ON M.[ID]=A.[KEY]
ORDER BY A.RANK DESC
 
RETURN

Stored Procedure, dışarıdan alınan aranan kelimeyi parametre olarak kullanacak ve sonuçları çağırıldığı ortama döndürecektir. Şimdi, asp.net sayfamızı aşağıdaki gibi oluşturalım.

Aşağıdaki kod, aranan kelimenin geçtiği makaleleri bulma ve bulunan makalelerin olduğu sayfalara link verme işlemini gerçekleştirmektedir. Kod, bir ASP.NET uygulamasında kullanılabilir ve bir Stored Procedure kullanarak SQL Injection saldırılarına karşı önlem almaktadır. Ayrıca, DataGrid kontrolü kullanılarak sonuçlar kullanıcıya sunulmaktadır.

<asp:DataGrid id="dgSonuclar" style="Z-INDEX: 105; LEFT: 48px; POSITION: absolute; TOP: 120px" runat="server" AutoGenerateColumns="False">
    <AlternatingItemStyle BackColor="#FFE0C0"></AlternatingItemStyle>
    <ItemStyle ForeColor="Black" BackColor="#CCCCCC"></ItemStyle>
    <Columns>
        <asp:HyperLinkColumn DataNavigateUrlField="ID" DataNavigateUrlFormatString="MakaleGoster.aspx?ID={0}" DataTextField="Konu" HeaderText="Makale Konusu"></asp:HyperLinkColumn>
        <asp:BoundColumn DataField="Tarih" SortExpression="Tarih" ReadOnly="True" HeaderText="Yayin Tarihi" DataFormatString="{0:dd-MM-yy}"></asp:BoundColumn>
    </Columns>
</asp:DataGrid>

private SqlConnection con;
private SqlCommand cmd;
private SqlDataAdapter da;
private DataTable dt;

private void BaslangicAyarlari()
{
    con = new SqlConnection("data source=localhost;initial catalog=bsenyurt;integrated security=SSPI");
    cmd = new SqlCommand("sp_AraBul", con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@Aranan", SqlDbType.NVarChar, 255);
    da = new SqlDataAdapter(cmd);
    dt = new DataTable();
}

private void Page_Load(object sender, System.EventArgs e)
{
    BaslangicAyarlari();
}

private void btnBul_Click(object sender, System.EventArgs e)
{
    cmd.Parameters["@Aranan"].Value = txtArananKelime.Text;
    try
    {
        if (con.State == ConnectionState.Closed)
            con.Open();
        da.Fill(dt);
        dgSonuclar.DataSource = dt;
        dgSonuclar.DataBind();
    }
    catch (SqlException hata)
    {
        Label1.Text = hata.Message.ToString();
    }
    finally
    {
        if (con.State == ConnectionState.Open)
            con.Close();
    }
}

Uygulama çalıştırıldığında, sonuçlar dgSonuclar DataGrid kontrolünde görüntülenecektir. Her makale başlığı, MakaleGoster.aspx sayfasına link olarak yerleştirilmiştir ve bu linklere tıklandığında ilgili makalenin detay sayfası açılacaktır.

Full-Text Searching (Tüm Metinde Arama) tekniği, sadece tek bir kelime üzerinden arama yapmak zorunda olmadığımızı ifade eder. Örneğin, “Matematik Mühendisi” kelimelerinin ardışık olarak geçtiği yerleri kolayca bulabiliriz. Ancak, bu tür bir arama sonucunda “Matematik Mühendisi” kelimesiyle tam eşleşen metinlerin bulunduğu satırların yanı sıra “mühendisi” kelimesinin olduğu, ancak “Matematik” kelimesinin olmadığı satırlar da elde edilecektir.

Ayrıca, içerik alanında hem “overload” kelimesi hem de “interface” kelimesi geçen makaleleri bulmak istediğimiz bir örnekle karşılaşırsak, mantıksal operatörlerin sunduğu imkanlardan yararlanmamız gerekecektir. Bunun için Full-Text Searching (Tüm Metinde Arama) işlemlerinde kullanabileceğimiz iki yeni SQL anahtar sözcüğü bulunmaktadır: “CONTAINS” ve “CONTAINSTABLE”. Bu anahtar sözcüklerde “AND”, “OR”, “NEAR”, “*” gibi mantıksal operatörler kullanarak arama işlemleri daha detaylı bir şekilde gerçekleştirilebilir.

Örneğin aşağıdaki sorgu, “overload” ve “interface” kelimelerinin bir arada geçtiği alanları arar:

Sonuç olarak, Full-Text Searching (Tüm Metinde Arama) tekniği sayesinde sadece tek bir kelime üzerinden değil, ardışık olarak geçen kelimeleri de bulabiliriz. Mantıksal operatorler olan AND, OR, NEAR, * gibi karakterler kullanarak arama işlemlerimizi daha detaylı hale getirebiliriz. Bunun yanı sıra, * asteriks karakteri de kullanarak belirli bir kelime ile başlayan sözcükleri içeren alanları bulabiliriz. CONTAINS ve CONTAINSTABLE anahtar sözcükleri ile bu operatörleri kullanabiliriz.

Sql Help’e bakarak diğer kullanabileceğimiz operatörleri de öğrenebiliriz. Umarım bu makale, Full-Text Searching (Tüm Metinde Arama) işlemlerini anlamanıza yardımcı olmuştur.