<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從一個實戰(zhàn)問題再談 Elasticsearch 數(shù)據(jù)建模

          共 3527字,需瀏覽 8分鐘

           ·

          2020-12-03 10:53

          1、上問題

          請問在一張訂單表里,用戶購買的產(chǎn)品是一條數(shù)據(jù),我現(xiàn)在想查既購買了 A 又買了 B 的用戶,這種需求能做嗎?

          在表里存在一個用戶購買了多種產(chǎn)品和一個產(chǎn)品被多個人購買的情況,每個用戶購買的產(chǎn)品是一條單獨的數(shù)據(jù)。

          假如現(xiàn)在的表已經(jīng)是我上邊說的那種情況了,能寫出符合我查詢要求的DSL嗎?

          球友提問

          2、問題細(xì)化

          注意,類似的問題是業(yè)務(wù)問題,如果要實際落地分析,需要進一步核實確認(rèn)當(dāng)前的數(shù)據(jù)建模。

          本質(zhì)一句話:數(shù)據(jù)的建模決定了數(shù)據(jù)的存儲,數(shù)據(jù)的存儲決定了數(shù)據(jù)的檢索實現(xiàn)。

          經(jīng)反復(fù)討論,敲定了當(dāng)前的簡化的數(shù)據(jù)建模如下:

          PUT?products
          {
          ??"mappings":?{
          ????"properties":?{
          ??????"uid":{
          ????????"type":"keyword"
          ??????},
          ??????"tag_name":{
          ????????"type":"keyword"
          ??????}
          ????}
          ??}
          }

          POST?products/_bulk
          {"index":{"_id":1}}
          {"tag_name":["陽光保險-2016"],?"uid":"1111_2222"}
          {"index":{"_id":2}}
          {"tag_name":"太平洋保險-2020",?"uid":"1111_2222"}
          {"index":{"_id":3}}
          {"tag_name":"平安保險-2019",?"uid":"333333"}

          兩個字段給大家簡單解讀一下:

          • uid,用戶id
          • "tag_name,用戶購買的產(chǎn)品

          如上的建模就和問題描述建立起一一對應(yīng)的關(guān)系了。

          用戶id為:1111_2222 的用戶,購買了 2 個產(chǎn)品:陽光保險-2016 和 太平洋保險-2020。

          現(xiàn)在問題轉(zhuǎn)嫁為:查找購買了“陽光保險-2016” 和 “太平洋保險-2020” 的用戶?

          到了這里,問題基本上無二義,雙方理解基本一致。

          ps:這也是咱們公司內(nèi)部溝通拆解問題的思路,由于問題比較簡單,不再啰嗦。

          3、問題剖析

          怎么做?

          看到這里,大家可以想一下?暫停幾秒,再往后看... ...

          這時候,腦海里想一下,檢索或者聚合能否實現(xiàn)類似需求?

          注意:購買了 “陽光保險-2016” 和 “太平洋保險-2020” ,是的關(guān)系。首先想到的是:bool 和 must 結(jié)合。

          很快啊,答案寫在了下面

          POST?products/_search
          {
          ??"query":?{
          ????"bool":?{
          ??????"must":?[
          ????????{
          ??????????"term":?{
          ????????????"tag_name":?"陽光保險-2016"
          ??????????}
          ????????},
          ????????{
          ??????????"term":?{
          ????????????"tag_name":?"太平洋保險-2020"
          ??????????}
          ????????}
          ??????]
          ????}
          ??}
          }

          但,放到 Kibana里面執(zhí)行一下,發(fā)現(xiàn)怎么返回結(jié)果為空?

          大意了嗎?!再仔細(xì)審題.....

          恍然大悟,本質(zhì)錯誤原因在于:一對一的字段映射關(guān)系,怎么能得到兩個或者多個都匹配的結(jié)果呢?

          這才意識到哪里出了問題?!——不是數(shù)據(jù)檢索,而是數(shù)據(jù)建模!

          4、問題解答

          問題的本質(zhì)再細(xì)化抽象:

          這已經(jīng)不是簡單的 Mysql 中的一對一的數(shù)據(jù)關(guān)系,所謂一對一代表 —— 一個用戶 id 對應(yīng)一個產(chǎn)品名。

          如下圖所示:多個 1 對 1 表示不同的doc。

          而是:一對多的數(shù)據(jù)關(guān)系。

          為什么?多個一對一是不能解決:查找購買了“陽光保險-2016” 和 “太平洋保險-2020” 的用戶的需求的?

          那怎么實現(xiàn)呢?幾乎沒有更好的方法,除了:數(shù)據(jù)重新建模。

          再建模的時候,要以上面的一對多的圖示作為依據(jù)。

          這時候,腦海里要浮現(xiàn)出 ES 支持哪些所謂“多表關(guān)聯(lián)”操作?

          至少應(yīng)該想到:

          • Array 數(shù)組類型
          • Object 對象類型
          • Nested 嵌套對象類型
          • Join 父子關(guān)聯(lián)類型

          我們先拿 Array 數(shù)組類型試驗,提到數(shù)組類型,里面要進一步映射出 Elasticsearch 關(guān)于數(shù)組的定義:

          • 在Elasticsearch中,沒有專用的數(shù)組數(shù)據(jù)類型。

          • 默認(rèn)情況下,任何字段都可以包含零個或多個值。

          • 數(shù)組中的所有值必須具有相同的數(shù)據(jù)類型。

          強調(diào)一下:根據(jù)數(shù)組的定義,之前定義的 Mapping 是不需要修改的。

          實踐一把:

          POST?products/_bulk
          {"index":{"_id":1}}
          {"tag_name":["陽光保險-2016",?"太平洋保險-2020"],?"uid":"1111_2222"}
          {"index":{"_id":2}}
          {"tag_name":"太平洋保險-2020",?"uid":"1111_2222"}
          {"index":{"_id":3}}
          {"tag_name":"平安保險-2019",?"uid":"333333"}

          如此,一對一的數(shù)據(jù)建模變成了一對多的數(shù)據(jù)建模。

          驗證一把結(jié)果是否達(dá)到預(yù)期呢?

          POST?products/_search
          {
          ??"query":?{
          ????"bool":?{
          ??????"must":?[
          ????????{
          ??????????"term":?{
          ????????????"tag_name":?"陽光保險-2016"
          ??????????}
          ????????},
          ????????{
          ??????????"term":?{
          ????????????"tag_name":?"太平洋保險-2020"
          ??????????}
          ????????}
          ??????]
          ????}
          ??}
          }

          返回結(jié)果(僅貼出了 hits 部分):

          ?"hits"?:?[
          ??????{
          ????????"_index"?:?"products",
          ????????"_type"?:?"_doc",
          ????????"_id"?:?"1",
          ????????"_score"?:?1.6161176,
          ????????"_source"?:?{
          ??????????"tag_name"?:?[
          ????????????"陽光保險-2016",
          ????????????"太平洋保險-2020"
          ??????????],
          ??????????"uid"?:?"1111_2222"
          ????????}
          ??????}
          ????]

          很簡單的就實現(xiàn)了需求。

          注意:Object,nested 等也可以實現(xiàn),要根據(jù)具體業(yè)務(wù)所需,不再展開講。

          5、再談數(shù)據(jù)建模

          為什么是再談,是因為我們強調(diào)過:干貨 | 論Elasticsearch數(shù)據(jù)建模的重要性。

          尤其基礎(chǔ)數(shù)據(jù)源來自關(guān)系型數(shù)據(jù)庫(Mysql、Oracle 等)的業(yè)務(wù)數(shù)據(jù),切記不要將數(shù)據(jù)同步到ES就完事大吉。

          同步之前需要討論:

          • 數(shù)據(jù)在 Elasticsearch 怎么建模?
          • Mapping 如何設(shè)置?
          • 哪些字段需要全文檢索?需要分詞?哪些不需要?
          • 哪些字段需要建索引?
          • 哪些字段不需要存儲?
          • 類型選擇:integer 還是 keyword?
          • 哪些需要做多表關(guān)聯(lián)?使用:寬表冗余存儲?還是 Array,Object,Nested,Join ?都需要深入考慮。
          • 哪些字段需要預(yù)處理?
          • 預(yù)處理是通過logstash filter 環(huán)節(jié)實現(xiàn)?還是 Mysql 視圖實現(xiàn)?還是 ingest 管道實現(xiàn)?還是其他?
            ......?
            類似延伸出幾十個問題都不在話下。

          這里想的越充分,后面越省事!

          關(guān)于多表關(guān)聯(lián)問題,推薦閱讀:Elasticsearch多表關(guān)聯(lián)設(shè)計指南

          6、小結(jié)

          數(shù)據(jù)建模的培養(yǎng)沒有太好的速成方法,需要結(jié)合項目實踐、反饋、再實踐、再反饋總結(jié)。形成知識積累。


          加微信:elastic6(僅有少量坑位了),和 BAT 大佬一起精進 Elastic 技術(shù)!

          推薦閱讀:
          Elasticsearch Top 51 重中之重面試題及答案
          Elasticsearch 搜索工程師筆試面試,請先看這 10 條建議!
          干貨 | BAT等一線大廠 Elasticsearch面試題解讀
          重磅 | 死磕 Elasticsearch 方法論認(rèn)知清單(2020年國慶更新版)
          能拿駕照就能通過 Elastic 認(rèn)證考試!

          短時間快習(xí)得多干貨!
          中國 近?50%+?Elastic 認(rèn)證工程師出自于此!
          全球?800+?Elastic 愛好者一起死磕 Elasticsearch!
          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  韩国精品二区 | 在线观看亚洲中文字幕 | 亚洲日韩黄色电影 | 人人添人人澡久久婷亚洲AV | 黑人内射精品 |