13 Ekim 2015 Salı

Elastic'le Join İşlemleri

1.Application-side Joins

Elastic'te Gamze kullanıcısına ait bloglara ulaşabilmek için 2 ayrı sorgu ile ulaşılabilir.

GET /gamze/user/_search
{
  "query": {
    "match": {
      "title": "Gamze"
    }
  }
}

GET /gamze/myblog/_search
{
  "query": {
    "filtered": {
      "filter": {
        "terms": { "user": [1] }  
      }
    }
  }
}

Bu join işleminin temel avantajı; veriyi normalize etmesidir, dezavantajı ise fazla sorgunun çalıştırılmasıdır. Bu yaklaşım, yukarıdaki örnekte user dökümanının küçük boyutlarda olması durumunda avantaj sağlayacaktır. Durum boyutu büyük olan dökümanlarda ise oldukça zorlaşacaktır.

2.Denormalizing Data

Bu yol Elastic'te istenen en iyi arama performansına sahiptir.

PUT /gamze/user/1
{
  "name":     "Gamze Ercan",
  "email":    "gamze@ercan.com",
  "dob":      "1985/10/24"
}

PUT /gamze/myblog/2
{
  "title":    "Relationships",
  "body":     "It's complicated...",
  "user":     {
    "id":       1,
    "name":     "Gamze Ercan" 
  }
}

Gamze kullanıcısına ait bloğa ulaşabilmek bu yöntemde blog dökümanında user verisi denormalize edilir.
Sorguyu aşağıdaki gibi gerçekleştiririz.

GET /gamze/myblog/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title":     "relationships" }},
        { "match": { "user.name": "Gamze "          }}
      ]
    }
  }
}

Denormalize olmuş verinin avantajı hızıdır. Çünkü her döküman istenen sorgu sonucuna ulaşılabilmesi için gerekli olan bütün verilere sahiptir.

3. Nested Objects

PUT /gamze/myblog/1
{
  "title": "Nest eggs",
  "body":  "Making your money work...",
  "tags":  [ "cash", "shares" ],
  "comments": [ 
    {
      "name":    "Gamze Ercan",
      "comment": "Great article",
      "age":     28,
      "stars":   4,
      "date":    "2015-10-01"
    },
    {
      "name":    "Alice White",
      "comment": "More like this please",
      "age":     31,
      "stars":   5,
      "date":    "2015-10-05"
    }
  ]
}

Yukarıda da görüldüğü gibi blog dökümanı bütün yorum bilgilerini içeriyor. Yani hepsi tek bir döküman içerisindedir. Bütün içerik tek bir dökümanda olursa hiç bir join işlemine gerek kalmaz. Böylece aramada iyi bir performans sergilenir.

Ama cross-object matching sebebiyle oluşan nesne aşağıdaki gibi gözükmektedir.

{
  "title":            [ eggs, nest ],
  "body":             [ making, money, work, your ],
  "tags":             [ cash, shares ],
  "comments.name":    [ alice, ercan, gamze , white ],
  "comments.comment": [ article, great, like, more, please, this ],
  "comments.age":     [ 28, 31 ],
  "comments.stars":   [ 4, 5 ],
  "comments.date":    [ 2015-10-01, 2015-10-05 ]
}

Yani Alice 28 ile, Gamze' de 2015-10-05 tarihiyle eşlemiş oluyor. Bu durum yüzünden veri kaybı gerçekleşiyor.

Aşağıdaki gibi Nested Objects bu duruma çözüm olmuştur.

{ 
  "comments.name":    [ gamze, ercan],
  "comments.comment": [ article, great ],
  "comments.age":     [ 28 ],
  "comments.stars":   [ 4 ],
  "comments.date":    [ 2015-10-01 ]
}
{ 
  "comments.name":    [ alice, white ],
  "comments.comment": [ like, more, please, this ],
  "comments.age":     [ 31 ],
  "comments.stars":   [ 5 ],
  "comments.date":    [ 2015-10-05 ]
}
{ 
  "title":            [ eggs, nest ],
  "body":             [ making, money, work, your ],
  "tags":             [ cash, shares ]
}

Sorgusu da bu şekilde gerçekleştirilir.

GET /my_index/blogpost/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "eggs" }}, 
        {
          "nested": {
            "path": "comments", 
            "query": {
              "bool": {
                "must": [ 
                  { "match": { "comments.name": "gamze" }},
                  { "match": { "comments.age":  28     }}
                ]
        }}}}
      ]
}}}

4.Parent-Child Relationship

Nested modele benzer bir yaklaşımdır. Nested modelde bütün verilerin tek bir dökümanda olmasına karşın bu yöntemde tamamiyle parent ve child'ın farklı dökümanlarda yer alır. Tek farkı budur. Bire çok ilişkisine sahiptir. 1 parent birden çok child a sahiptir.

Nested modele karşı avantajları ise;

  • Parent dökümanı child dökümanını etkilemeden güncellenebilir.
  • Child dökümanlara, diğer childları yada parentı etkilemeden veri ekleme, güncelleme veya silme işlemleri gerçekleştirilebilir.

PUT /company
{
  "mappings": {
    "branch": {},
    "employee": {
      "_parent": {
        "type": "branch" 
      }
    }
  }
}

Bu örnekte branch tipinde bir parent ve employee tipinde child ilişkisi gösteriliyor.

Bu örnekle ilgili ayrıntılı açıklamalar buradadır.



Hiç yorum yok:

Yorum Gönder