Regex İle Veritabanında Akıllı Arama

regexÜzerinde çalıştığım projede kullanıcılar arama işlemlerini yaptıkları zaman türkçe karakterler de aramama gibi bir sorun yaşıyorduk. Bunun nedeni arama yapılan sütunda genellikle deneme like ‘%kelime%’ şeklinde yapılan aramalarda kelıme gibi olan yazıları ne yazık ki bulmuyordu. Düşündüm ki bu kadar regex’i sevdiğim halde neden bu arama kısımlarında da regex kullanmıyorum. Buna yönelik olarak farklı yerlerde de kullanılabilecek gibi bir kaç satır kod yazarak bu sıkıntıyı çözmüş oldum. Tabi bu kısımda da bazı eksikliklerin olduğu gerçek. O eksiklikleri tamamlayıp yazıyı tekrar en kısa zaman güncellemeyi düşünüyorum.

Not: Kod sadece MySql için çalışmaktadır. Diğer Veritabanlarında ne yazık ki çalışmayacaktır. Aynı zamanda UTF8 kullandığınızda türkçe ı karakteri ile aramalarda sorun çıkıyor. Bu durumda sqlinizi çalıştırmadan önce set names utf8 sqlini çalıştırırsanız sorun ortadan kalkacaktır.

    using System;

    using System.Collections.Generic;

    using System.Text;

    public class SmartSearchClass

    {

        private List IntegerColumns { get; set; }

        private List StringColumns { get; set; }

        public SmartSearchClass()

        {

            this.IntegerColumns = new List();

            this.StringColumns = new List();

        }

        public void AddInt(string column, ColumnSearchType columnSearchType = ColumnSearchType.Equal)

        {

            this.IntegerColumns.Add(new SearchItem(column, columnSearchType));

        }

        public void AddString(string column, ColumnSearchType columnSearchType = ColumnSearchType.Between)

        {

            this.StringColumns.Add(new SearchItem(column, columnSearchType));

        }

        public string GetSearchSql(string searchTerm)

        {

            string returnValue;

            var sqlParts = new List();

            var splitedWords = searchTerm.Split(new[] { ” ” }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < splitedWords.Length; i++)

            {

                var word = splitedWords[i];

                if (this.IsInt(word))

                {

                    for (int j = 0; j < this.IntegerColumns.Count; j++)

                    {

                        switch (this.IntegerColumns[j].ColumnSearchType)

                        {

                            case ColumnSearchType.Between:

                                sqlParts.Add(this.IntegerColumns[i].Column + ” like ‘%” + word + “%'”);

                                break;

                            case ColumnSearchType.Left:

                                sqlParts.Add(this.IntegerColumns[i].Column + ” like ‘” + word + “%'”);

                                break;

                            case ColumnSearchType.Right:

                                sqlParts.Add(this.IntegerColumns[i].Column + ” like ‘%” + word + “‘”);

                                break;

                            case ColumnSearchType.Equal:

                                sqlParts.Add(this.IntegerColumns[i].Column + ” = ” + word);

                                break;

                        }

                    }

                }

                else

                {

                    for (int j = 0; j < this.StringColumns.Count; j++)

                    {

                        switch (this.StringColumns[j].ColumnSearchType)

                        {

                            case ColumnSearchType.Between:

                                sqlParts.Add(this.StringColumns[i].Column + ” regexp ‘” + this.GetRegexText(word) + “‘”);

                                break;

                            case ColumnSearchType.Left:

                                sqlParts.Add(

                                    this.StringColumns[i].Column + ” regexp ‘$” + this.GetRegexText(word) + “‘”);

                                break;

                            case ColumnSearchType.Right:

                                sqlParts.Add(

                                    this.StringColumns[i].Column + ” regexp ‘” + this.GetRegexText(word) + “$'”);

                                break;

                            case ColumnSearchType.Equal:

                                sqlParts.Add(

                                    this.StringColumns[i].Column + ” regexp ‘^” + this.GetRegexText(word) + “$'”);

                                break;

                        }

                    }

                }

            }

            returnValue = “(” + string.Join(” OR “, sqlParts) + “)”;

            return returnValue;

        }

        private bool IsInt(string word)

        {

            int intValue;

            return int.TryParse(word, out intValue);

        }

        public class SearchItem

        {

            public SearchItem(string column, ColumnSearchType columnSearchType)

            {

                this.Column = column;

                this.ColumnSearchType = columnSearchType;

            }

            public string Column { get; set; }

            public ColumnSearchType ColumnSearchType { get; set; }

        }

        private string GetRegexText(string text)

        {

            var returnValue = new StringBuilder();

            foreach (var c in text)

            {

                switch (c)

                {

                    case ‘e’:

                    case ‘ə’:

                        returnValue.Append(“[əe]”);

                        break;

                    case ‘E’:

                    case ‘Ə’:

                        returnValue.Append(“[ƏE]”);

                        break;

                    case ‘h’:

                    case ‘x’:

                        returnValue.Append(“[hx]”);

                        break;

                    case ‘H’:

                    case ‘X’:

                        returnValue.Append(“[HX]”);

                        break;

                    case ‘c’:

                    case ‘ç’:

                        returnValue.Append(“[cç]”);

                        break;

                    case ‘ı’:

                    case ‘i’:

                        returnValue.Append(“[ıi]”);

                        break;

                    case ‘I’:

                    case ‘İ’:

                        returnValue.Append(“[Iİ]”);

                        break;

                    case ‘k’:

                    case ‘q’:

                    case ‘g’:

                    case ‘ğ’:

                        returnValue.Append(“[qgğk]”);

                        break;

                    case ‘K’:

                    case ‘Q’:

                    case ‘G’:

                    case ‘Ğ’:

                        returnValue.Append(“[QGĞK]”);

                        break;

                    case ‘ü’:

                    case ‘u’:

                        returnValue.Append(“[uü]”);

                        break;

                    case ‘ş’:

                    case ‘s’:

                        returnValue.Append(“[sş]”);

                        break;

                    case ‘Ş’:

                    case ‘S’:

                        returnValue.Append(“[ŞS]”);

                        break;

                    case ‘ö’:

                    case ‘o’:

                        returnValue.Append(“[öo]”);

                        break;

                    case ‘Ö’:

                    case ‘O’:

                        returnValue.Append(“[ÖO]”);

                        break;

                    default:

                        returnValue.Append(c);

                        break;

                }

            }

            return returnValue.ToString();

        }

    }

    public enum ColumnSearchType

    {

        Between,

        Left,

        Right,

        Equal

    }

Kullanımı:

SmartSearchClass smartSearch = new SmartSearchClass();

smartSearch.AddInt(“mt.id”);

smartSearch.AddString(“mt.adi”);

smartSearch.AddString(“mt.barkod”);

var smartSearchSql = smartSearch.GetSearchSql(“Erhan Barış”);

AddInt ile girilen Integer değer için arama, AddString ise isminde de anlaşılacağı gibi string alanlar için arama yapmasına karar verdiğimiz kısım.

İşte bu da sonuç.

(mt.adi regexp ‘[ƏE]r[hx]an’ OR mt.adi regexp ‘[ƏE]r[hx]an’ OR mt.barkod regexp ‘Bar[ıi][sş]’ OR mt.barkod regexp ‘Bar[ıi][sş]’)

Facebook Comments

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir