Elasticsearch Mapping

22 Oca

Elasticsearch dünyasında mapping, bir dokümanın (document) ve onun alanlarının (fields) nasıl tutulacağı ve indeksleneceğini belirtir.

Mapping tanımlamalarının düzgün yapılması ile;

  • Elasticsearch performansı optimize edilir.
  • Disk alanlarından tasarruf edilir.

(Bu yazıda, doküman indeksleme işlemleri sırasında gösterilen örnekler, kibana developer tools üzerinden yapılabilir.)

Doküman indexleme

Aşağıdaki istek ile bir doküman indeksi oluşturmak mümkündür.

POST <index-name>/_doc
{
  "field": "value"
}

Örnek:

POST fruits/_doc
{
  "name": "Banana",
  "produce_type": "Fruit",
  "date_purchased": "2020-06-02T12:15:35",
  "quantity": 120,
  "unit_price": 6.21,
  "description": "a tropical fruit.",
  "vendor_details": {
    "vendor": "Tropical Fruit Growers of Turkey",
    "contact": "Bayram Üçüncü",
    "location": "Turkey"
  }
}

Bu istek çalıştırıldığında aşağıdaki gibi bir cevap dönecektir.

{
  "_index" : "fruits",
  "_type" : "_doc",
  "_id" : "68LPgn4BbIMmYeUuNtYB",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

Elasticsearch üzerinde indeksler için iki tür mapping oluşturma yöntemi vardır. Bunlar;

  • Dynamic mapping (Dinamik Eşleştirme)
  • Explicit mapping (Önceden Belirlenen Eşleştirme)

Dynamic Mapping (Dinamik Eşleştirme)

Bir kullanıcı yukarıdaki örnekte olduğu gibi mapping tanımını önceden yapmadığında, Elasticsearch eşlemeyi varsayılan olarak gerektiği gibi oluşturur veya günceller. Bu dinamik eşleştirme (dynamic mapping) olarak bilinir.

Dinamik eşleştirmede, alan tipleri veri içeriğinden çıkarılmaktadır. Bu noktada eğer index oluşturulurken girilen verilerden biri sayısal olarak girilmişse ve başka verilere göre metinsel değerler de alabilecek durumdaysa, örneğin float olarak oluşturulan bir alana metinsel bir ifade yazılmaya çalışıldığında hata oluşacaktır.

Dinamik eşleme ile Elasticsearch her alana bakar ve alan içeriğinden veri türünü çıkarmaya çalışır. Ardından, her alana bir tür atar ve eşleme olarak bilinen alan adları ve türlerin bir listesini oluşturur.

Atanan alan türüne bağlı olarak, her alan dizine alınır ve farklı istek türleri (full text search, aggregations, sorting) için hazırlanır. Bu nedenle eşleştirme, Elasticsearch’ün verileri nasıl depoladığı ve aradığı konusunda önemli bir rol oynar.

Bir indekse ait mapping değerlerine ulaşmak için şu sorgu çalıştırılabilir.

GET fruits/_mapping
{
  "fruits" : {
    "mappings" : {
      "properties" : {
        "date_purchased" : {
          "type" : "date"
        },
        "description" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "produce_type" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "quantity" : {
          "type" : "long"
        },
        "unit_price" : {
          "type" : "float"
        },
        "vendor_details" : {
          "properties" : {
            "contact" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "location" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "vendor" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        }
      }
    }
  }
}

Mapping JSON verisi içerisinde, indeksteki alanların adlarının ve türlerinin bir listesini bulunur. Elasticsearch alan türleri (field types) bilgilerine detaylı olarak buradan ulaşılabilir.

Metin İndeksleme

Metinsel alanlar için iki farklı tür bulunur:

  1. Text field
  2. Keyword field

Varsayılan olarak, her string, metin (text) alanı ve anahtar kelime (keyword) çoklu alanı olarak iki kez eşlenir. Her alan türü, farklı istek türleri için hazırlanır.

Text alan türü, full-text search yapabilmek için tasarlanmıştır.

Keyword alan türü, kesin aramalar (exact searches), toplamlar (Aggregations) ve sıralamalar (sorting) için tasarlanmıştır.

Text Field (Metin Alanlar)

Metin Analizi

Elasticsearch’te arama yaptığınızda, büyük/küçük harfe duyarlı olmadığını veya noktalama işaretlerinin önemi yoktur. Bunun nedeni, veriler indekse eklendiğinde, metin analizinin gerçekleşmesidir.

Varsayılan olarak, metinler indekse alındığında analiz edilir. Metin, belirteçler (token) olarak da bilinen ayrık sözcüklere bölünür. Çözümleyici (analyzer), her kelimeyi küçük harflere dönüştürür ve noktalama işaretlerini kaldırır.

Analiz sonucunda ortaya çıkan metinler, bir inverted index tablosuna kaydedilir.

Bu işlem, indekse her doküman eklendiğinde tekrarlanır. Zamanla inverted index tablosu aşağıdaki gibi değişikliğe uğrar.

Bu durumda, “this book” şeklinde bir arama yapıldığında, arama sonucunda 1,2,3 numaralı dokümanlar bulunur.

Keyword Field (Anahtar Alanlar)

Keyword alanlar, kesin aramalar, toplamlar ve sıralamalar için kullanılır. Aranan değerlerde, ilgili dokümanın sahip olduğu değerleri bulmak için doküman kimliğini tarar

PUT fruits/_doc/1
{
  "country": "İstanbul"
}
PUT fruits/_doc/2
{
  "country": "Ankara"
}
PUT fruits/_doc/3
{
  "country": "Manisa"
}
PUT fruits/_doc/4
{
  "country": "Trabzon"
}
PUT fruits/_doc/5
{
  "country": "Van"
}
PUT fruits/_doc/6
{
  "country": "Antalya"
}
PUT fruits/_doc/7
{
  "country": "Bolu"
}

Elasticsearch sizin için dinamik olarak bir eşleme oluşturduğunda, bir metni ne için kullanmak istediğinizi bilemez, bu nedenle tüm metinleri her iki alan türüne eşler. Örneğin vendor alanı:

            "vendor" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }

Her iki alan türüne de ihtiyacınız olmadığı durumlarda, disk alanları israf edilmiş olur. Çünkü inverted index kullanımına gerek olmayan durumlarda gereksiz yere inverted index alanları oluşturulmuş olur.

Explicit Mapping (Önceden Belirlenen Eşleştirme)

Mapping (tip eşleştirme) işlemini kendiniz tanımlamak istediğiniz durumlarda, bunu index oluşturma sırasında yapabilirsiniz. Bu sayede eşleştirme tanımını kendiniz tasarlayabilirsiniz. Örneğin:

  • Hangi metinsel alanların Full-text search alanları olarak ele alınacağını belirtebilirsiniz.
  • Hangi alanların sayı, tarih veya geolocation olacağını belirtebilirsiniz.
  • Tarih alanlarının biçimini belirtebilirsiniz.
  • Kaynak kullanımını ve performansı dengelemek için çalışma zamanı alanlarını (runtime fields) indekse alınmış alanlarla birlikte kullanabilirsiniz. Index daha küçük olacaktır, ancak arama performansı daha yavaş olacaktır.

Her index için tek bir eşleştirme (mapping) belirlenir. İndeks oluşturulduktan sonra, bir eşlemeye yalnızca yeni alanlar eklenebilir. Mevcut bir alanın eşleşmesi değiştirilemez. Eğer mevcut bir alanın türünün değiştirilmesi gerekiyorsa, istenen eşlemeyle yeni bir indeks oluşturulur ve ardından tüm dokümanlar yeni dizine yeniden aktarılır.

PUT fruit_index
{

    "index": {
      "number_of_replicas": "1",
      "number_of_shards": "2"
    },
    "mappings" : {
      "properties" : {
        "date_purchased" : {
          "type" : "date"
        },
        "description" : {
          "type" : "text"
        },
        "name" : {
          "type" : "text"
        },
        "produce_type" : {
          "type" : "text"
        },
        "quantity" : {
          "type" : "long"
        },
        "unit_price" : {
          "type" : "float"
        },
        "vendor_details" : {
          "enabled" : false
        }
      }
    }
}

Field tanımlamaları properties içerisinde belirtilmektedir. Her field için ad ve tip belirtilmektedir. Kendi oluşturduğunuz eşleştirmelerde gereksiz alan tanımlamalarını iptal ederek optimum bir indeks oluşturabilirsiniz. Oluşturduğunuz indekslerde, alanlara istediğiniz analyzer atamalarını yapabilirsiniz.

Dikkat

Bir indekste çok fazla alan tanımlamak, yetersiz bellek hatalarına ve kurtarılması zor durumlardan kaynaklanabilecek bir eşleme patlamasına neden olabilir. Eklenen her yeni belgenin dinamik eşleme gibi yeni alanlar sunduğu bir durumu düşünün. Her yeni alan, indekste mapping olarak eklenir ve mapping büyüdükçe bir sorun haline gelebilir. Bu durumlara karşı Elasticsearch ayarlarında “mapping limit settings” kullanılarak, mapping alan sayısı sınırlandırılabilir.

Kaynaklar

  • https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
  • https://github.com/LisaHJung/Part-5-Understanding-Mapping-with-Elasticsearch-and-Kibana
  • https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime-mapping-fields.html
  • https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-settings-limit.html