Elasticsearch Sorgularını Azure Cosmos DB’ye Çevirmek
Elasticsearch tarafında tek bir arama isteği eşleşen dokümanları, vurgulanmış metin parçalarını ve facet (aggregation) kovalarını aynı yanıtta döndürebiliyor. Azure Cosmos DB’ye geçerken bu bütünleşik yapı parçalanıyor: sıralı sonuçlar için bir sorgu, her facet alanı için ayrı birer toplama sorgusu, vurgulama gibi sunum işleri içinse uygulama katmanı. Microsoft’un Azure Cosmos DB blogunda yayımlanan çeviri rehberi bu adımları sırayla anlatıyor; hangi Elasticsearch yeteneği doğrudan karşılık buluyor, hangisi ek çaba istiyor, süreçte ne değişiyor.
Temel yaklaşım: tek istek yerine ayrık sorgular
Elasticsearch’te hits, highlight ve aggregations aynı istekte birlikte gelir. Azure Cosmos DB’de ise sorumlulukları ayırmak daha net bir model sunuyor:
- Bir sorgu, sıralanmış sonuç sayfasını getirir.
- Ayrı toplama sorguları, facet sayımlarını hesaplar.
- Vurgulama (highlighting) gibi gösterim özellikleri uygulama tarafında üretilir.
Bu ayrım, aynı tam metin koşulunun sorguların her birinde tekrarlanması demek. Facet sayımları ile sonuç listesi böyle tutarlı kalıyor.
Adım 1: Sıralı sonuç sorgusunu çevirmek
Başlangıç noktası, “shoes” terimini title, description, brand ve category alanlarında arayan bir multi_match sorgusu. İstek ilk 20 sonucu dönduruyor.
Elasticsearch:
{
"from": 0,
"size": 20,
"query": {
"bool": {
"must": [{
"multi_match": {
"query": "shoes",
"fields": ["title^3", "description",
"brand^2", "category"],
"type": "best_fields",
"fuzziness": "AUTO"
}
}]
}
}
}
Azure Cosmos DB:
SELECT *
FROM c
WHERE (
FullTextContains(c.title, 'shoes')
OR FullTextContains(c.description, 'shoes')
OR FullTextContains(c.brand, 'shoes')
OR FullTextContains(c.category, 'shoes')
)
ORDER BY RANK FullTextScore(c.title, ['shoes'])
OFFSET 0 LIMIT 20
Amaç her Elasticsearch yapısının birebir karşılığını üretmek değil, çekirdek arama davranışını korumak. Elasticsearch’teki title^3 ve brand^2 ifadeleri alan ağırlıklandırmasıdır (field boost); bu alanlardaki eşleşmelerin ilgi puanına katkısını artırır.
Azure Cosmos DB for NoSQL tam metin aramasında alan ağırlıklandırma şu an desteklenmiyor, dolayısıyla yukarıdaki sorgu bu çarpanları yeniden üretmiyor. Sonuçlar yerleşik BM25 tabanlı tam metin puanlama modeliyle sıralanıyor. İlgi puanına alan ağırlıkları katkı yaptığında dönen sonuç kümesi ve sıralama düzeni Elasticsearch ile birebir aynı olmayacak. Yine de BM25 modeli ilgili eşleşmeleri öne çıkarmak üzere tasarlandı; sıralama birebir olmasa da anlamlı sonuçlar bekleyebilirsiniz.
Adım 2: Kategorik facet’leri ayrı toplama sorgularına bölmek
Elasticsearch sorgusu kategori, alt kategori ve markayı tek istekte aggregation kovaları olarak dönduruyor:
"categories": {
"terms": { "field": "category.keyword", "size": 20 }
},
"subcategories": {
"terms": { "field": "subcategory.keyword", "size": 30 }
},
"brands": {
"terms": { "field": "brand.keyword", "size": 30 }
}
Azure Cosmos DB’de her alan için ayrı bir toplama sorgusu çalıştırılır. Her sorgu, sonuç sorgusundaki metin koşulunu tekrarlar ve bir facet anahtarı ile sayım döndürür.
Kategori:
SELECT
c.category AS facetKey,
COUNT(1) AS facetCount
FROM c
WHERE (
FullTextContains(c.title, 'shoes')
OR FullTextContains(c.description, 'shoes')
OR FullTextContains(c.brand, 'shoes')
OR FullTextContains(c.category, 'shoes')
)
GROUP BY c.category
Alt kategori:
SELECT
c.subcategory AS facetKey,
COUNT(1) AS facetCount
FROM c
WHERE (
FullTextContains(c.title, 'shoes')
OR FullTextContains(c.description, 'shoes')
OR FullTextContains(c.brand, 'shoes')
OR FullTextContains(c.category, 'shoes')
)
GROUP BY c.subcategory
Marka:
SELECT
c.brand AS facetKey,
COUNT(1) AS facetCount
FROM c
WHERE (
FullTextContains(c.title, 'shoes')
OR FullTextContains(c.description, 'shoes')
OR FullTextContains(c.brand, 'shoes')
OR FullTextContains(c.category, 'shoes')
)
GROUP BY c.brand
Ne değişiyor: Tüm kovaları tek yanıtta almak yerine uygulama odaklı toplama sorguları gönderir, dönen sayımları da sonuç listesiyle birleştirir.
Adım 3: Türetilmiş puan (rating) kovaları
Elasticsearch tarafında rating facet’i, her değeri gruplamadan önce taban (floor) değerine dönüştüren bir script ile üretiliyor:
"ratings": {
"terms": {
"script": "Math.floor(doc['rating'].value)",
"size": 5
}
}
Azure Cosmos DB’de aynı sonuca, türetilmiş değeri doğrudan SQL içinde ifade ederek varılıyor:
SELECT
FLOOR(c.rating) AS facetKey,
COUNT(1) AS facetCount
FROM c
WHERE (
FullTextContains(c.title, 'shoes')
OR FullTextContains(c.description, 'shoes')
OR FullTextContains(c.brand, 'shoes')
OR FullTextContains(c.category, 'shoes')
)
GROUP BY FLOOR(c.rating)
Ne değişiyor: Elasticsearch’te kova değerini aggregation içindeki script üretir, Azure Cosmos DB’de ise FLOOR(c.rating) hem SELECT hem GROUP BY içinde kullanılır. Çıktı tipi aynı kalıyor: her puan kovası için bir satır ve o kovaya düşen doküman sayısı.
Adım 4: Fiyat aralığı facet’leri
Elasticsearch sorgusu sabit fiyat aralıkları tanımlayıp her kova için sayım dönduruyor:
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "key": "Under $25", "to": 25 },
{ "key": "$25 - $50", "from": 25, "to": 50 },
{ "key": "$50 - $100", "from": 50, "to": 100 },
{ "key": "$100 - $200", "from": 100, "to": 200 },
{ "key": "$200 - $500", "from": 200, "to": 500 },
{ "key": "$500+", "from": 500 }
]
}
}
Azure Cosmos DB’de aynı çıktıyı koşullu toplama ifadeleri veriyor; her SUM belirli bir fiyat aralığına düşen dokümanları sayar:
SELECT
SUM(c.price < 25 ? 1 : 0) AS under25,
SUM(c.price >= 25 AND c.price < 50 ? 1 : 0) AS r25to50,
SUM(c.price >= 50 AND c.price < 100 ? 1 : 0) AS r50to100,
SUM(c.price >= 100 AND c.price < 200 ? 1 : 0) AS r100to200,
SUM(c.price >= 200 AND c.price < 500 ? 1 : 0) AS r200to500,
SUM(c.price >= 500 ? 1 : 0) AS over500
FROM c
WHERE (
FullTextContains(c.title, 'shoes')
OR FullTextContains(c.description, 'shoes')
OR FullTextContains(c.brand, 'shoes')
OR FullTextContains(c.category, 'shoes')
)
Ne değişiyor: Elasticsearch fiyat aralıklarını özel bir range aggregation’ı olarak ele alır; Azure Cosmos DB’de her aralık SELECT yan tümcesinde koşullu bir sayıma dönüşür. Sorgu, sonuç sorgusuyla aynı tam metin koşulunu kullandığı için fiyat kovaları yalnızca geçerli aramaya uyan dokümanları sayıyor, facet sayımları da sonuç listesiyle hizalı kalıyor.
Fiyat sınırları kullanıcının ne aradığına göre değişebildiğinden bunları önceden hesaplamak genellikle varsayılan çözüm değil. Dilerseniz FLOOR(c.rating) gibi türetilmiş bir anahtara göre de gruplayabilirsiniz.
Adım 5: Vurgulamayı uygulama katmanında ele almak
Elasticsearch isteği, title ve description alanları için vurgulanmış parçalar ve mark etiketleri tanımlıyor:
"highlight": {
"pre_tags": [""],
"post_tags": [""],
"fields": {
"title": { "number_of_fragments": 1, "fragment_size": 200 },
"description": { "number_of_fragments": 2, "fragment_size": 150 }
}
}
Azure Cosmos DB, tam metin sorgu yanıtının parçası olarak vurgulanmış metin parçaları döndürmüyor. Bu davranışı yeniden üretmek için arama sorgusu normal şekilde çalıştırılır, ardından uygulama katmanında eşleşen terimler title ve description gibi alanlarda bulunup … gibi görsel işaretlemeyle sarmalanır. Yerel (native) hit highlighting özelliği ise halen geliştirme aşamasında.
Çevrilen aramayı çalıştırma sırası
- Sonuç sorgusunu çalıştırın. Sıralı sorgu ile eşleşen dokümanların geçerli sayfasını alın.
- Gerekli facet sorgularını çalıştırın. Aynı arama durumu için kategori, alt kategori, marka, puan ve fiyat toplamalarını hesaplayın.
- Aktif filtreleri her yerde uygulayın. Kullanıcı aramayı daralttığında, bu filtreyi arayüzü tazelemeden önce hem sonuç sorgusuna hem de tüm toplama sorgularına ekleyin.
- Deneyimi oluşturun. Sonuçları, sayımları ve istemci tarafı vurgulamaları birlikte gösterin ki gezinme tutarlı bir sonuç kümesini yansıtsın.
Yalnızca söz dizimini değil, davranışı doğrulayın
Doğrulamaya temsili bir arama terimi ve doküman kümesiyle başlamak, sonra üretime benzer veriyle tekrarlamak öneriliyor. Karşılaştırılacak başlıklar sıralı sonuçlar, seçili filtreler, facet sayımları, sayfalama davranışı, request unit tüketimi ve uçtan uca gecikme. Bu adım sayesinde çeviri bir söz dizimi alıştırması olmaktan çıkıp uygulama düzeyinde doğrulamaya dönüşüyor.
Serinin bütünü
Bu yazı, Azure Cosmos DB blogundaki üç bölümlük serinin sonuncusu. İlk bölüm Elasticsearch kullanıcıları için genel geçiş yolunu tanıtıyor, ikinci bölüm Elasticsearch eşlemelerinin (mapping) Azure Cosmos DB indeksleme ve tam metin arama yapılandırmasına nasıl çevrileceğini ele alıyor. Bu bölümde ise arama isteğinin sorgulara dönüştürülmesi işleniyor.
Üç yazı birlikte, Elasticsearch tabanlı arama yüklerini Azure Cosmos DB’ye taşımayı değerlendirmek için bir başlangıç çerçevesi sunuyor: özellik modelini anlamak, indeksleme yapılandırmasını eşlemek ve sorgu desenlerini çevirmek. Daha fazla ayrıntı için Azure Cosmos DB tam metin arama dokümantasyonuna bakabilirsiniz.
Kaynaklar ve İleri Okuma
- Translating an Elasticsearch Search Request to Azure Cosmos DB (Madeline Egan, Azure Cosmos DB Blog)
- Azure Cosmos DB tam metin arama dokümantasyonu
- Azure Cosmos DB Blog
- Azure Cosmos DB’ye Elasticsearch’ten Geçiş Rehberi







Yorum gönder