7.1-對(duì)象及 Nested 對(duì)象

數(shù)據(jù)的關(guān)聯(lián)關(guān)系

  • 真實(shí)世界中有很多重要的關(guān)聯(lián)關(guān)系

    • 博客 / 作者 / 評(píng)論

    • 銀?賬戶有多次交易記錄

    • 客戶有多個(gè)銀?賬戶

    • ?錄?件有多個(gè)?件和??錄

關(guān)系型數(shù)據(jù)庫(kù)的范式化設(shè)計(jì)

關(guān)系型數(shù)據(jù)庫(kù)的范式化設(shè)計(jì)
1NF – 消除?主屬性對(duì)鍵的部分函數(shù)依賴
2NF – 消除?主要屬性對(duì)鍵的傳遞函數(shù)依賴
3NF – 消除主屬性對(duì)鍵的傳遞函數(shù)依賴
BCNF –主屬性不依賴于主屬性
  • 范式化設(shè)計(jì)(Normalization)的主要?標(biāo)是“減少不必要 的更新”

  • 副作?:?個(gè)完全范式化設(shè)計(jì)的數(shù)據(jù)庫(kù)會(huì)經(jīng)常?臨 “查詢緩慢”的問題

  • 數(shù)據(jù)庫(kù)越范式化,就需要 Join 越多的表

  • 范式化節(jié)省了存儲(chǔ)空間,但是存儲(chǔ)空間卻越來(lái)越便宜

  • 范式化簡(jiǎn)化了更新,但是數(shù)據(jù)“讀”取操作可能更多

Denormalization

  • 反范式化設(shè)計(jì)

    • 數(shù)據(jù) “Flattening”,不使?關(guān)聯(lián)關(guān)系胸哥,?是在?檔中保存冗余的數(shù)據(jù)拷?
  • 優(yōu)點(diǎn):?需處理 Joins 操作,數(shù)據(jù)讀取性能好

    • Elasticsearch 通過壓縮 _source 字段,減少磁盤空間的開銷
  • 缺點(diǎn):不適合在數(shù)據(jù)頻繁修改的場(chǎng)景

    • ?條數(shù)據(jù)(?戶名)的改動(dòng)火邓,可能會(huì)引起很多數(shù)據(jù)的更新

在 Elasticsearch 中處理關(guān)聯(lián)關(guān)系

  • 關(guān)系型數(shù)據(jù)庫(kù),?般會(huì)考慮 Normalize 數(shù)據(jù)德撬;在 Elasticsearch铲咨,往往考慮 Denormalize 數(shù)據(jù)

    • Denormalize 的好處:讀的速度變快 / ?需表連接 / ?需?鎖
  • Elasticsearch 并不擅?處理關(guān)聯(lián)關(guān)系。我們?般采?以下四種?法處理關(guān)聯(lián)

    • 對(duì)象類型

    • 嵌套對(duì)象(Nested Object)

    • ??關(guān)聯(lián)關(guān)系(Parent / Child )

    • 應(yīng)?端關(guān)聯(lián)

案例 1:博客和其作者信息

  • 對(duì)象類型

    • 在每?博客的?檔中都保留作者的信息

    • 如果作者信息發(fā)?變化蜓洪,需要修改相關(guān)的 博客?檔

# 插入一條 Blog 信息
PUT blog/_doc/1
{
  "content":"I like Elasticsearch",
  "time":"2019-01-01T00:00:00",
  "user":{
    "userid":1,
    "username":"Jack",
    "city":"Shanghai"
  }
}
  • 通過?條查詢即可獲取到博客和作者信息
# 查詢 Blog 信息
POST blog/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"content": "Elasticsearch"}},
        {"match": {"user.username": "Jack"}}
      ]
    }
  }
}

res:
"max_score" : 0.5753642,
"hits" : [
  {
    "_index" : "blog",
    "_type" : "_doc",
    "_id" : "1",
    "_score" : 0.5753642,
    "_source" : {
      "content" : "I like Elasticsearch",
      "time" : "2019-01-01T00:00:00",
      "user" : {
        "userid" : 1,
        "username" : "Jack",
        "city" : "Shanghai"
      }
    }
  }
]

案例 2:包含對(duì)象數(shù)組的?檔

DELETE my_movies

# 電影的Mapping信息
PUT my_movies
{
      "mappings" : {
      "properties" : {
        "actors" : {
          "properties" : {
            "first_name" : {
              "type" : "keyword"
            },
            "last_name" : {
              "type" : "keyword"
            }
          }
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
}


# 寫入一條電影信息
POST my_movies/_doc/1
{
  "title":"Speed",
  "actors":[
    {
      "first_name":"Keanu",
      "last_name":"Reeves"
    },

    {
      "first_name":"Dennis",
      "last_name":"Hopper"
    }

  ]
}

# 查詢電影信息
POST my_movies/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"actors.first_name": "Keanu"}},
        {"match": {"actors.last_name": "Hopper"}}
      ]
    }
  }

}
res:

"hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.723315,
    "hits" : [
      {
        "_index" : "my_movies",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.723315,
        "_source" : {
          "title" : "Speed",
          "actors" : [
            {
              "first_name" : "Keanu",
              "last_name" : "Reeves"
            },
            {
              "first_name" : "Dennis",
              "last_name" : "Hopper"
            }
          ]
        }
      }
    ]
  }


為什么會(huì)搜到不需要的結(jié)果纤勒?

  • 存儲(chǔ)時(shí),內(nèi)部對(duì)象的邊界并沒有考慮在內(nèi)蝠咆,JSON 格式被處理成扁平式鍵值對(duì)的結(jié)構(gòu)

  • 當(dāng)對(duì)多個(gè)字段進(jìn)?查詢時(shí)踊东,導(dǎo)致了意外的搜索結(jié)果

  • 可以? Nested Data Type 解決這個(gè)問題

image.png

什么是 Nested Data Type

  • Nested 數(shù)據(jù)類型:允許對(duì)象數(shù)組中的 對(duì)象被獨(dú)?索引

  • 使? nested 和 properties 關(guān)鍵字,將所有 actors 索引到多個(gè)分隔的?檔

  • 在內(nèi)部刚操, Nested ?檔會(huì)被保存在兩個(gè) Lucene ?檔中闸翅,在查詢時(shí)做 Join 處理

DELETE my_movies
# 創(chuàng)建 Nested 對(duì)象 Mapping
PUT my_movies
{
      "mappings" : {
      "properties" : {
        "actors" : {
          "type": "nested",
          "properties" : {
            "first_name" : {"type" : "keyword"},
            "last_name" : {"type" : "keyword"}
          }},
        "title" : {
          "type" : "text",
          "fields" : {"keyword":{"type":"keyword","ignore_above":256}}
        }
      }
    }
}

嵌套查詢

  • 在內(nèi)部, Nested ?檔會(huì)被保存在兩個(gè) Lucene ?檔中菊霜,會(huì)在查詢時(shí)做 Join 處理
image.png
# Nested 查詢
POST my_movies/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"title": "Speed"}},
        {
          "nested": {
            "path": "actors",
            "query": {
              "bool": {
                "must": [
                  {"match": {
                    "actors.first_name": "Keanu"
                  }},

                  {"match": {
                    "actors.last_name": "Hopper"
                  }}
                ]
              }
            }
          }
        }
      ]
    }
  }
}

嵌套聚合

# 普通 aggregation不工作
POST my_movies/_search
{
  "size": 0,
  "aggs": {
    "NAME": {
      "terms": {
        "field": "actors.first_name",
        "size": 10
      }
    }
  }
}

# Nested Aggregation
POST my_movies/_search
{
  "size": 0,
  "aggs": {
    "actors": {
      "nested": {
        "path": "actors"
      },
      "aggs": {
        "actor_name": {
          "terms": {
            "field": "actors.first_name",
            "size": 10
          }
        }
      }
    }
  }
}

res:
"aggregations" : {
    "actors" : {
      "doc_count" : 2,
      "actor_name" : {
        "doc_count_error_upper_bound" : 0,
        "sum_other_doc_count" : 0,
        "buckets" : [
          {
            "key" : "Dennis",
            "doc_count" : 1
          },
          {
            "key" : "Keanu",
            "doc_count" : 1
          }
        ]
      }
    }
  }

本節(jié)知識(shí)點(diǎn)

  • 在 Elasticsearch 中坚冀,往往會(huì) Denormalize 數(shù)據(jù)的?式建模(使?對(duì)象的?式)

    • 好處是:讀寫的速度變快 / ?需表連接 / ?需?鎖
  • 如果?檔的更新并不頻繁,可以在?檔中使?對(duì)象

  • 當(dāng)對(duì)象包含了多值對(duì)象時(shí)

    • 可以使?嵌套對(duì)象(Nested Object)解決查詢正確性的問題

課程demos

DELETE blog
# 設(shè)置blog的 Mapping
PUT /blog
{
  "mappings": {
    "properties": {
      "content": {
        "type": "text"
      },
      "time": {
        "type": "date"
      },
      "user": {
        "properties": {
          "city": {
            "type": "text"
          },
          "userid": {
            "type": "long"
          },
          "username": {
            "type": "keyword"
          }
        }
      }
    }
  }
}


# 插入一條 Blog 信息
PUT blog/_doc/1
{
  "content":"I like Elasticsearch",
  "time":"2019-01-01T00:00:00",
  "user":{
    "userid":1,
    "username":"Jack",
    "city":"Shanghai"
  }
}


# 查詢 Blog 信息
POST blog/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"content": "Elasticsearch"}},
        {"match": {"user.username": "Jack"}}
      ]
    }
  }
}


DELETE my_movies

# 電影的Mapping信息
PUT my_movies
{
      "mappings" : {
      "properties" : {
        "actors" : {
          "properties" : {
            "first_name" : {
              "type" : "keyword"
            },
            "last_name" : {
              "type" : "keyword"
            }
          }
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
}


# 寫入一條電影信息
POST my_movies/_doc/1
{
  "title":"Speed",
  "actors":[
    {
      "first_name":"Keanu",
      "last_name":"Reeves"
    },

    {
      "first_name":"Dennis",
      "last_name":"Hopper"
    }

  ]
}

# 查詢電影信息
POST my_movies/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"actors.first_name": "Keanu"}},
        {"match": {"actors.last_name": "Hopper"}}
      ]
    }
  }

}

DELETE my_movies
# 創(chuàng)建 Nested 對(duì)象 Mapping
PUT my_movies
{
      "mappings" : {
      "properties" : {
        "actors" : {
          "type": "nested",
          "properties" : {
            "first_name" : {"type" : "keyword"},
            "last_name" : {"type" : "keyword"}
          }},
        "title" : {
          "type" : "text",
          "fields" : {"keyword":{"type":"keyword","ignore_above":256}}
        }
      }
    }
}


POST my_movies/_doc/1
{
  "title":"Speed",
  "actors":[
    {
      "first_name":"Keanu",
      "last_name":"Reeves"
    },

    {
      "first_name":"Dennis",
      "last_name":"Hopper"
    }

  ]
}

# Nested 查詢
POST my_movies/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"title": "Speed"}},
        {
          "nested": {
            "path": "actors",
            "query": {
              "bool": {
                "must": [
                  {"match": {
                    "actors.first_name": "Keanu"
                  }},

                  {"match": {
                    "actors.last_name": "Hopper"
                  }}
                ]
              }
            }
          }
        }
      ]
    }
  }
}


# Nested Aggregation
POST my_movies/_search
{
  "size": 0,
  "aggs": {
    "actors": {
      "nested": {
        "path": "actors"
      },
      "aggs": {
        "actor_name": {
          "terms": {
            "field": "actors.first_name",
            "size": 10
          }
        }
      }
    }
  }
}


# 普通 aggregation不工作
POST my_movies/_search
{
  "size": 0,
  "aggs": {
    "NAME": {
      "terms": {
        "field": "actors.first_name",
        "size": 10
      }
    }
  }
}

相關(guān)閱讀

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鉴逞,一起剝皮案震驚了整個(gè)濱河市记某,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌构捡,老刑警劉巖液南,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異勾徽,居然都是意外死亡滑凉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門喘帚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)畅姊,“玉大人,你說我怎么就攤上這事吹由∪粑矗” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵倾鲫,是天一觀的道長(zhǎng)粗合。 經(jīng)常有香客問我萍嬉,道長(zhǎng),這世上最難降的妖魔是什么舌劳? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任帚湘,我火速辦了婚禮,結(jié)果婚禮上甚淡,老公的妹妹穿的比我還像新娘大诸。我一直安慰自己,他們只是感情好贯卦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布资柔。 她就那樣靜靜地躺著,像睡著了一般撵割。 火紅的嫁衣襯著肌膚如雪贿堰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天啡彬,我揣著相機(jī)與錄音羹与,去河邊找鬼。 笑死庶灿,一個(gè)胖子當(dāng)著我的面吹牛纵搁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播往踢,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼腾誉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了峻呕?” 一聲冷哼從身側(cè)響起利职,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘦癌,沒想到半個(gè)月后猪贪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡讯私,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年哮伟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妄帘。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖池凄,靈堂內(nèi)的尸體忽然破棺而出抡驼,到底是詐尸還是另有隱情,我是刑警寧澤肿仑,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布致盟,位于F島的核電站碎税,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏馏锡。R本人自食惡果不足惜雷蹂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望杯道。 院中可真熱鬧匪煌,春花似錦、人聲如沸党巾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)齿拂。三九已至驳规,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間署海,已是汗流浹背吗购。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留砸狞,地道東北人捻勉。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像趾代,于是被迫代替她去往敵國(guó)和親贯底。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容