ElasticSearch Skor Yapısı | C#

Merhaba, elasticsearch’ü büyük veriler içerisinde daha performanslı aramalar yapmak için kullanmıştık.
Aslında çok çok daha yetenekli bir arkadaş.
Belki ilerleyen zamanda daha detaylı kullanma durumu ortaya çıkar da, biraz daha derinlerine inersem, tespit ettiğim faydalı bilgileri de paylaşırım.
Gerçek hayattan bir örnek:
Bir malzemeye ait 7-8 tane farklı özellik var.
Bu bir araç parçası.
Bunun markası var, modeli var, malzeme numarası var, orijinal referansı var, açıklaması var, kategorisi var,…vs.
Kullanıcının yazdığı değer bunların her birinde geçiyor olabilir.
Ama örneğin malzeme numarası ile örtüşüyorsa diğerlerine göre daha yukarıda onu göstermek doğrusu.
İşte bunu yapabilmek adına şu şekilde bir skor mantığı kullandık.

QueryContainer filtreSkorMalzemeNo = null; 		// En değerli alan bu.
QueryContainer filtreSkorReferansOe = null;		// İkinci seviyede değerli alan bu.
QueryContainer filtreSkorAciklama = null; 		// En az değerli alan bu.
filtreSkorMalzemeNo = new WildcardQuery() { Field = "arama_malzeme_no", Value = "*" + anahtarKelime + "*" };
filtreSkorReferansOe = new WildcardQuery() { Field = "arama_referans_oe", Value = "*" + anahtarKelime + "*" };
filtreSkorAciklama = new WildcardQuery() { Field = "arama_aciklama", Value = "*" + anahtarKelime + "*" };
QueryContainer sorguIcerenAnd = null;
QueryContainer sorguIcerenOr = null;
QueryContainer sorguEsitAnd = null;	
QueryContainer sorguAna = null;
// Sorgularımızı seçilen değerlere göre doldurduğunuzu varsayıyorum burada...
///.....
//....
sorguAna = sorguIcerenAnd & sorguEsitAnd & sorguAralikAnd & sorguIcerenOr;
Func<QueryContainerDescriptor<malzemeler>, QueryContainer> fo = fonksiyonSkorParamGetir(filtreSkorAciklama, filtreSkorMalzemeNo, filtreSkorReferansOe, sorguAna);
ISearchResponse<malzemeler> aramaSonucMalzeme = skoraGoreAra(filtre, fo, 100); // Toplam 100 puan alamayan sonuçlar gelmesin istiyoruz.
if (aramaSonucMalzeme.Total == 0)
{
    aramaSonucMalzeme = skoraGoreAra(filtre, fo, 1); // Eğer hiç malzeme bulamadıysak da artık ne bulduysan getir lanet olsun diyoruz...
}

private Func<QueryContainerDescriptor<malzemeler>, QueryContainer> fonksiyonSkorParamGetir(QueryContainer filtreSkorAciklama, QueryContainer filtreSkorMalzemeNo, QueryContainer filtreSkorReferansOe, QueryContainer sorguAna)
{
	return new Func<QueryContainerDescriptor<malzemeler>, QueryContainer>(q => q
		.FunctionScore(fsc => fsc
			.BoostMode(FunctionBoostMode.Sum)
			.ScoreMode(FunctionScoreMode.Sum)
			.Functions(fu => fu
				.Weight(w => w
					.Weight(10)
					.Filter(wf => wf
					.Bool(bb => bb
					.Must(filtreSkorAciklama))
					))
				.Weight(w => w
					.Weight(200)
					.Filter(wf => wf
					.Bool(bb => bb
					.Must(filtreSkorReferansOe))
					))
				.Weight(w => w
					.Weight(1000)
					.Filter(wf => wf
					.Bool(bb => bb
					.Must(filtreSkorMalzemeNo))
					))
				)
				.Query(q2 => q2
					.Bool(b => b
					.Should(sorguAna))
				)
	));
}

private static ISearchResponse<malzemeler> skoraGoreAra(UrunAramaFiltre filtre, Func<QueryContainerDescriptor<malzemeler>, QueryContainer> fo, double? skorAltLimit)
{
	return SrvSabitler.ElasticSorgu.Search<malzemeler>(s => s
		.RequestConfiguration(r => r.DisableDirectStreaming())
		.From(filtre.SayfaNo == 1 ? 0 : (filtre.SayfaNo * filtre.SayfaBasinaKayitSayisi) - filtre.SayfaBasinaKayitSayisi)
		.Size(filtre.SayfaBasinaKayitSayisi)
		.Sort(t => !string.IsNullOrEmpty(filtre.MalzemeNo) ? t.Ascending(sa => sa.malzeme_no) : t.Descending(SortSpecialField.Score).Ascending(r => r.malzeme_no))
		.MinScore(skorAltLimit)
		.Query(fo)
	);
}	

Selamlar.

Leave a Reply

Your email address will not be published. Required fields are marked *