elasticsearch之六Mapping映射

個人專題目錄


1. Mapping映射入門

1.1 什么是mapping映射

概念:自動或手動為index中的_doc建立的一種數(shù)據(jù)結構和相關配置石咬,簡稱為mapping映射步淹。Mapping決定了index中的field的特征措伐。

插入幾條數(shù)據(jù)民晒,讓es自動為我們建立一個索引

PUT /website/_doc/1
{
  "post_date": "2019-01-01",
  "title": "my first article",
  "content": "this is my first article in this website",
  "author_id": 11400
}

PUT /website/_doc/2
{
  "post_date": "2019-01-02",
  "title": "my second article",
  "content": "this is my second article in this website",
  "author_id": 11400
}
 
PUT /website/_doc/3
{
  "post_date": "2019-01-03",
  "title": "my third article",
  "content": "this is my third article in this website",
  "author_id": 11400
}

動態(tài)映射:dynamic mapping尾序,自動為我們建立index,以及對應的mapping势篡,mapping中包含了每個field對應的數(shù)據(jù)類型,以及如何分詞等設置模暗。

重點:我們當然,后面會講解念祭,也可以手動在創(chuàng)建數(shù)據(jù)之前兑宇,先創(chuàng)建index,以及對應的mapping

GET  /website/_mapping/
{
  "website" : {
    "mappings" : {
      "properties" : {
        "author_id" : {
          "type" : "long"
        },
        "content" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "post_date" : {
          "type" : "date"
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

嘗試各種搜索

GET /website/_search?q=2019        0條結果             
GET /website/_search?q=2019-01-01           1條結果
GET /website/_search?q=post_date:2019-01-01     1條結果
GET /website/_search?q=post_date:2019          0 條結果

搜索結果為什么不一致粱坤,因為es自動建立mapping的時候隶糕,設置了不同的field不同的data type。不同的data type的分詞站玄、搜索等行為是不一樣的枚驻。所以出現(xiàn)了_all field和post_date field的搜索表現(xiàn)完全不一樣。

1.2 精確匹配與全文搜索的對比分析

exact value 精確匹配

2019-01-01株旷,exact value再登,搜索的時候,必須輸入2019-01-01晾剖,才能搜索出來

如果你輸入一個01锉矢,是搜索不出來的

select * from book where name= 'java'

full text 全文檢索

搜“筆記電腦”,筆記本電腦詞條會不會出現(xiàn)齿尽。

select * from book where name like '%java%'

(1)縮寫 vs. 全稱:cn vs. china

(2)格式轉化:like liked likes

(3)大小寫:Tom vs tom

(4)同義詞:like vs love

2019-01-01沽损,2019 01 01,搜索2019循头,或者01绵估,都可以搜索出來

china,搜索cn卡骂,也可以將china搜索出來

likes国裳,搜索like,也可以將likes搜索出來

Tom偿警,搜索tom躏救,也可以將Tom搜索出來

like,搜索love螟蒸,同義詞盒使,也可以將like搜索出來

就不是說單純的只是匹配完整的一個值,而是可以對值進行拆分詞語后(分詞)進行匹配七嫌,也可以通過縮寫少办、時態(tài)、大小寫诵原、同義詞等進行匹配英妓。深入 NPL,自然語義處理挽放。

1.3 全文檢索下倒排索引核心原理快速揭秘

重建倒排索引

normalization正規(guī)化,建立倒排索引的時候蔓纠,會執(zhí)行一個操作辑畦,也就是說對拆分出的各個單詞進行相應的處理,以提升后面搜索的時候能夠搜索到相關聯(lián)的文檔的概率

時態(tài)的轉換腿倚,單復數(shù)的轉換纯出,同義詞的轉換,大小寫的轉換

mom ―> mother

liked ―> like

small ―> little

dogs ―> dog

1.4 query string根據(jù)字段分詞策略

query string必須以和index建立時相同的analyzer進行分詞

query string對exact value和full text的區(qū)別對待

如: date:exact value 精確匹配

? text: full text 全文檢索

1.5 mapping總結

  1. 往es里面直接插入數(shù)據(jù)敷燎,es會自動建立索引暂筝,同時建立對應的mapping。(dynamic mapping)

  2. mapping中就自動定義了每個field的數(shù)據(jù)類型

  3. 不同的數(shù)據(jù)類型(比如說text和date)硬贯,可能有的是exact value焕襟,有的是full text

  4. exact value,在建立倒排索引的時候饭豹,分詞的時候鸵赖,是將整個值一起作為一個關鍵詞建立到倒排索引中的;full text拄衰,會經(jīng)歷各種各樣的處理卫漫,分詞,normaliztion(時態(tài)轉換肾砂,同義詞轉換列赎,大小寫轉換),才會建立到倒排索引中镐确。

  5. 同時包吝,exact value和full text類型的field就決定了,在一個搜索過來的時候源葫,對exact value field或者是full text field進行搜索的行為也是不一樣的诗越,會跟建立倒排索引的行為保持一致;比如說exact value搜索的時候息堂,就是直接按照整個值進行匹配嚷狞,full text query string,也會進行分詞和normalization再去倒排索引中去搜索

  6. 可以用es的dynamic mapping荣堰,讓其自動建立mapping床未,包括自動設置數(shù)據(jù)類型;也可以提前手動創(chuàng)建index和tmapping振坚,自己對各個field進行設置薇搁,包括數(shù)據(jù)類型,包括索引行為渡八,包括分詞器啃洋,等传货。

1.6 mapping的核心數(shù)據(jù)類型以及dynamic mapping

核心的數(shù)據(jù)類型

字符型:string,string類型包括
text 和 keyword

text類型被用來索引長文本宏娄,在建立索引前會將這些文本進行分詞靶草,轉化為詞的組合蓖柔,建立索引挺智。允許es來檢索這些詞語钦奋。text類型不能用來排序和聚合揍瑟。

Keyword類型不需要進行分詞邓梅,可以被用來檢索過濾励背、排序和聚合漂洋。keyword 類型字段只能用本身來進行檢索

數(shù)字型:long, integer, short, byte, double, float
日期型:date
布爾型:boolean
二進制型:binary

詳見:https://www.elastic.co/guide/en/elasticsearch/reference/7.3/mapping-types.html

復雜數(shù)據(jù)類型(Complex datatypes)

數(shù)組類型(Array datatype):數(shù)組類型不需要專門指定數(shù)組元素的type祖乳,例如:
    字符型數(shù)組: [ "one", "two" ]
    整型數(shù)組:[ 1, 2 ]
    數(shù)組型數(shù)組:[ 1, [ 2, 3 ]] 等價于[ 1, 2, 3 ]
    對象數(shù)組:[ { "name": "Mary", "age": 12 }, { "name": "John", "age": 10 }]
對象類型(Object datatype):_ object _ 用于單個JSON對象逗堵;
嵌套類型(Nested datatype):_ nested _ 用于JSON數(shù)組;

地理位置類型(Geo datatypes)

地理坐標類型(Geo-point datatype):_ geo_point _ 用于經(jīng)緯度坐標眷昆;
地理形狀類型(Geo-Shape datatype):_ geo_shape _ 用于類似于多邊形的復雜形狀蜒秤;

特定類型(Specialised datatypes)

IPv4 類型(IPv4 datatype):_ ip _ 用于IPv4 地址;
Completion 類型(Completion datatype):_ completion _提供自動補全建議亚斋;
Token count 類型(Token count datatype):_ token_count _ 用于統(tǒng)計做了標記的字段的index數(shù)目作媚,該值會一直增加,不會因為過濾條件而減少帅刊。
mapper-murmur3
類型:通過插件纸泡,可以通過 _ murmur3 _ 來計算 index 的 hash 值;
附加類型(Attachment datatype):采用 mapper-attachments
插件赖瞒,可支持_ attachments _ 索引女揭,例如 Microsoft Office 格式,Open Document 格式栏饮,ePub, HTML 等吧兔。

dynamic mapping 推測規(guī)則

true or false -> boolean

123 -> long

123.123 -> double

2018-01-01 -> date

hello world -> text

[] -> array

{} -> object

在上述的自動mapping字段類型分配的時候,只有text類型的字段需要分詞器袍嬉。默認分詞器是standard分詞器境蔼。

查看mapping

GET /index/_mapping/

{
  "test_index": { # 索引名
    "mappings": { # 映射列表
      "test_type": { # 類型名
        "properties": { # 字段列表
          "age": { # 字段名
            "type": "long" # 字段類型
          },
          "gender": {
            "type": "text",
            "fields": { # 子字段列表
              "keyword": { # 子字段名
                "type": "keyword", # 子字段類型,keyword不進行分詞處理的文本類型
                "ignore_above": 256 # 子字段存儲數(shù)據(jù)長度
              }
            }
          },
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

1.7 手動管理mapping

查詢所有索引的映射

GET /_mapping

創(chuàng)建映射

創(chuàng)建索引后伺通,應該立即手動創(chuàng)建映射

PUT book/_mapping
{
    "properties": {
           "name": {
                  "type": "text"
            },
           "description": {
              "type": "text",
              "analyzer":"english",
              "search_analyzer":"english"
           },
           "pic":{
             "type":"text",
             "index":false
           },
           "studymodel":{
             "type":"text"
           }
    }
}

Text 文本類型

  1. analyzer

通過analyzer屬性指定分詞器箍土。

上邊指定了analyzer是指在索引和搜索都使用english,如果單獨想定義搜索時使用的分詞器則可以通過search_analyzer屬性罐监。

  1. index

index屬性指定是否索引涮帘。

默認為index=true,即要進行索引笑诅,只有進行索引才可以從索引庫搜索到调缨。

但是也有一些內容不需要索引疮鲫,比如:商品圖片地址只被用來展示圖片,不進行搜索圖片弦叶,此時可以將index設置為false俊犯。

刪除索引,重新創(chuàng)建映射伤哺,將pic的index設置為false燕侠,嘗試根據(jù)pic去搜索,結果搜索不到數(shù)據(jù)立莉。

  1. store

是否在source之外存儲绢彤,每個文檔索引后會在 ES中保存一份原始文檔,存放在"_source"中蜓耻,一般情況下不需要設置store為true茫舶,因為在_source中已經(jīng)有一份原始文檔了。

  1. boost

字段級別的分數(shù)加權刹淌,默認值是1.0

  1. doc_values

對not_analyzed字段饶氏,默認都是開啟,分詞字段不能使用有勾,對排序和聚合能提升較大性能疹启,節(jié)約內存

  1. fielddata":{"format":"disabled"}

針對分詞字段,參與排序或聚合時能提高性能蔼卡,不分詞字段統(tǒng)一建議使用doc_value

  1. "fields":{"raw":{"type":"string","index":"not_analyzed"}}

可以對一個字段提供多種索引模式喊崖,同一個字段的值,一個分詞雇逞,一個不分詞

  1. "ignore_above":100

超過100個字符的文本贷祈,將會被忽略,不被索引

  1. "include_in_all":ture

設置是否此字段包含在_all字段中喝峦,默認是true势誊,除非index設置成no選項

"index_options":"docs"http://4個可選參數(shù)docs(索引文檔號) ,freqs(文檔號+詞頻),positions(文檔號+詞頻+位置谣蠢,通常用來距離查詢)粟耻,offsets(文檔號+詞頻+位置+偏移量,通常被使用在高亮字段)分詞字段默認是position眉踱,其他的默認是docs

"norms":{"enable":true,"loading":"lazy"}//分詞字段默認配置挤忙,不分詞字段:默認{"enable":false},存儲長度因子和索引時boost谈喳,建議對需要參與評分字段使用 册烈,會額外增加內存消耗量

"null_value":"NULL"http://設置一些缺失字段的初始化值,只有string可以使用婿禽,分詞字段的null值也會被分詞

"position_increament_gap":0//影響距離查詢或近似查詢赏僧,可以設置在多值字段的數(shù)據(jù)上火分詞字段上大猛,查詢時可指定slop間隔,默認值是100

"search_analyzer":"ik"http://設置搜索時的分詞器淀零,默認跟ananlyzer是一致的挽绩,比如index時用standard+ngram,搜索時用standard用來完成自動提示功能

"similarity":"BM25"http://默認是TF/IDF算法驾中,指定一個字段評分策略唉堪,僅僅對字符串型和分詞類型有效

"term_vector":"no"http://默認不存儲向量信息,支持參數(shù)yes(term存儲)肩民,with_positions(term+位置),with_offsets(term+偏移量)唠亚,with_positions_offsets(term+位置+偏移量) 對快速高亮fast vector highlighter能提升性能,但開啟又會加大索引體積持痰,不適合大數(shù)據(jù)量用

測試

PUT book/_mapping
{
        "properties": {
           "name": {
                  "type": "text"
            },
           "description": {
              "type": "text",
              "analyzer":"english",
              "search_analyzer":"english"
           },
           "pic":{
             "type":"text",
             "index":false
           },
           "studymodel":{
             "type":"text"
           }
    }
}

插入文檔:

PUT /book/_doc/1
{
  "name":"Bootstrap開發(fā)框架",
  "description":"Bootstrap是由Twitter推出的一個前臺頁面開發(fā)框架灶搜,在行業(yè)之中使用較為廣泛。此開發(fā)框架包含了大量的CSS共啃、JS程序代碼,可以幫助開發(fā)者(尤其是不擅長頁面開發(fā)的程序人員)輕松的實現(xiàn)一個不受瀏覽器限制的精美界面效果暂题。",
  "pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
  "studymodel":"201002"
}

Get /book/_search?q=name:開發(fā)

Get /book/_search?q=description:開發(fā)

Get /book/_search?q=pic:group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg

Get /book/_search?q=studymodel:201002

通過測試發(fā)現(xiàn):name和description都支持全文檢索移剪,pic不可作為查詢條件。

keyword關鍵字字段

目前已經(jīng)取代了"index": false薪者。上邊介紹的text文本字段在映射時要設置分詞器纵苛,keyword字段為關鍵字字段,通常搜索keyword是按照整體搜索言津,所以創(chuàng)建keyword字段的索引時是不進行分詞的攻人,比如:郵政編碼、手機號碼悬槽、身份證等怀吻。keyword字段通常用于過慮、排序初婆、聚合等蓬坡。

date日期類型

日期類型不用設置分詞器。

通常日期類型的字段用于排序磅叛。

通過format設置日期格式

例子:

下邊的設置允許date字段存儲年月日時分秒屑咳、年月日及毫秒三種格式。

{
    "properties": {
        "timestamp": {
          "type":   "date",
          "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
        }
      }
}

插入文檔:

Post book/doc/3 
{
"name": "spring開發(fā)基礎",
"description": "spring 在java領域非常流行弊琴,java程序員都在用兆龙。",
"studymodel": "201001",
 "pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
 "timestamp":"2018-07-04 18:28:58"
}

數(shù)值類型

下邊是ES支持的數(shù)值類型

  1. 盡量選擇范圍小的類型,提高搜索效率

  2. 對于浮點數(shù)盡量用比例因子敲董,比如一個價格字段紫皇,單位為元慰安,我們將比例因子設置為100這在ES中會按 分 存儲,映射如下:

"price": {
        "type": "scaled_float",
        "scaling_factor": 100
  },

由于比例因子為100坝橡,如果我們輸入的價格是23.45則ES中會將23.45乘以100存儲在ES中泻帮。

如果輸入的價格是23.456,ES會將23.456乘以100再取一個接近原始值的數(shù)计寇,得出2346锣杂。

使用比例因子的好處是整型比浮點型更易壓縮,節(jié)省磁盤空間番宁。

如果比例因子不適合元莫,則從下表選擇范圍小的去用:

更新已有映射,并插入文檔:

PUT book/doc/3
{
"name": "spring開發(fā)基礎",
"description": "spring 在java領域非常流行蝶押,java程序員都在用踱蠢。",
"studymodel": "201001",
 "pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
 "timestamp":"2018-07-04 18:28:58",
 "price":38.6
}

修改映射

只能創(chuàng)建index時手動建立mapping,或者新增field mapping棋电,但是不能update field mapping茎截。

因為已有數(shù)據(jù)按照映射早已分詞存儲好。如果修改赶盔,那這些存量數(shù)據(jù)怎么辦企锌。

新增一個字段mapping

PUT /book/_mapping/
{
  "properties" : {
    "new_field" : {
      "type" :    "text",
     "index":    "false"
    }
  }
}

如果修改mapping,會報錯

PUT /book/_mapping/
{
  "properties" : {
    "studymodel" : {
     "type" :    "keyword"
    }
  }
}

返回:

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "mapper [studymodel] of different type, current_type [text], merged_type [keyword]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "mapper [studymodel] of different type, current_type [text], merged_type [keyword]"
  },
  "status": 400
}

刪除映射

通過刪除索引來刪除映射。

1.8 定制dynamic mapping

定制dynamic策略

true:遇到陌生字段于未,就進行dynamic mapping

false:新檢測到的字段將被忽略撕攒。這些字段將不會被索引,因此將無法搜索烘浦,但仍將出現(xiàn)在返回點擊的源字段中抖坪。這些字段不會添加到映射中,必須顯式添加新字段闷叉。

strict:遇到陌生字段擦俐,就報錯

創(chuàng)建mapping

PUT /my_index
{
    "mappings": {
      "dynamic": "strict",
       "properties": {
        "title": {
          "type": "text"
        },
        "address": {
          "type": "object",
          "dynamic": "true"
        }
        }
    }
}

插入數(shù)據(jù)

PUT /my_index/_doc/1
{
  "title": "my article",
  "content": "this is my article",
  "address": {
    "province": "guangdong",
    "city": "guangzhou"
  }
}

報錯

{
  "error": {
    "root_cause": [
      {
        "type": "strict_dynamic_mapping_exception",
        "reason": "mapping set to strict, dynamic introduction of [content] within [_doc] is not allowed"
      }
    ],
    "type": "strict_dynamic_mapping_exception",
    "reason": "mapping set to strict, dynamic introduction of [content] within [_doc] is not allowed"
  },
  "status": 400
}

自定義 dynamic mapping策略

es會根據(jù)傳入的值,推斷類型握侧。

date_detection 日期探測

默認會按照一定格式識別date捌肴,比如yyyy-MM-dd。但是如果某個field先過來一個2017-01-01的值藕咏,就會被自動dynamic mapping成date状知,后面如果再來一個"hello world"之類的值,就會報錯孽查〖玻可以手動關閉某個type的date_detection,如果有需要,自己手動指定某個field為date類型西设。

PUT /my_index
{
    "mappings": {
      "date_detection": false,
       "properties": {
        "title": {
          "type": "text"
        },
        "address": {
          "type": "object",
          "dynamic": "true"
        }
        }
    }
}

測試

PUT /my_index/_doc/1
{
  "title": "my article",
  "content": "this is my article",
  "address": {
    "province": "guangdong",
    "city": "guangzhou"
  },
  "post_date":"2019-09-10"
}

查看映射

GET /my_index/_mapping

自定義日期格式

PUT my_index
{
  "mappings": {
    "dynamic_date_formats": ["MM/dd/yyyy"]
  }
}

插入數(shù)據(jù)

PUT my_index/_doc/1
{
  "create_date": "09/25/2019"
}

numeric_detection 數(shù)字探測

雖然json支持本機浮點和整數(shù)數(shù)據(jù)類型瓣铣,但某些應用程序或語言有時可能將數(shù)字呈現(xiàn)為字符串。通常正確的解決方案是顯式地映射這些字段贷揽,但是可以啟用數(shù)字檢測(默認情況下禁用)來自動完成這些操作棠笑。

PUT my_index
{
  "mappings": {
    "numeric_detection": true
  }
}
PUT my_index/_doc/1
{
  "my_float":   "1.0", 
  "my_integer": "1" 
}

定制自己的dynamic mapping template

PUT /my_index
{
    "mappings": {
            "dynamic_templates": [
                { 
                  "en": {
                      "match":              "*_en", 
                      "match_mapping_type": "string",
                      "mapping": {
                          "type":           "text",
                          "analyzer":       "english"
                      }
                }                  
            }
        ]
    }
}

插入數(shù)據(jù)

PUT /my_index/_doc/1
{
  "title": "this is my first article"
}

PUT /my_index/_doc/2
{
  "title_en": "this is my first article"
}

搜索

GET my_index/_search?q=first
GET my_index/_search?q=is

title沒有匹配到任何的dynamic模板,默認就是standard分詞器禽绪,不會過濾停用詞蓖救,is會進入倒排索引,用is來搜索是可以搜索到的

title_en匹配到了dynamic模板印屁,就是english分詞器循捺,會過濾停用詞,is這種停用詞就會被過濾掉雄人,用is來搜索就搜索不到了

模板寫法

PUT my_index
{
  "mappings": {
    "dynamic_templates": [
      {
        "integers": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "integer"
          }
        }
      },
      {
        "strings": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "fields": {
              "raw": {
                "type":  "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    ]
  }
}

模板參數(shù)

"match":   "long_*",
"unmatch": "*_text",
"match_mapping_type": "string",
"path_match":   "name.*",
"path_unmatch": "*.middle",
"match_pattern": "regex",
"match": "^profit_\d+$"

場景

1結構化搜索

默認情況下从橘,elasticsearch將字符串字段映射為帶有子關鍵字字段的文本字段。但是础钠,如果只對結構化內容進行索引恰力,而對全文搜索不感興趣,則可以僅將“字段”映射為“關鍵字”旗吁。請注意踩萎,這意味著為了搜索這些字段,必須搜索索引所用的完全相同的值阵漏。

    {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "keyword"
          }
        }
      }

2僅搜索

與前面的示例相反驻民,如果您只關心字符串字段的全文搜索翻具,并且不打算對字符串字段運行聚合履怯、排序或精確搜索,您可以告訴彈性搜索將其僅映射為文本字段(這是5之前的默認行為)

    {
        "strings_as_text": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text"
          }
        }
      }

3norms 不關心評分

norms是指標時間的評分因素裆泳。如果您不關心評分叹洲,例如,如果您從不按評分對文檔進行排序工禾,則可以在索引中禁用這些評分因子的存儲并節(jié)省一些空間运提。

{
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }

1.9 復雜數(shù)據(jù)類型

multivalue field

{ "tags": [ "tag1", "tag2" ]}

建立索引時與string是一樣的,數(shù)據(jù)類型不能混

empty field

null闻葵,[]民泵,[null]

object field

PUT /company/_doc/1
{
  "address": {
    "country": "china",
    "province": "guangdong",
    "city": "guangzhou"
  },
  "name": "jack",
  "age": 27,
  "join_date": "2019-01-01"
}

address:object類型

查詢映射

GET /company/_mapping
{
  "company" : {
    "mappings" : {
      "properties" : {
        "address" : {
          "properties" : {
            "city" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "country" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "province" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        },
        "age" : {
          "type" : "long"
        },
        "join_date" : {
          "type" : "date"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

object

{
  "address": {
    "country": "china",
    "province": "guangdong",
    "city": "guangzhou"
  },
  "name": "jack",
  "age": 27,
  "join_date": "2017-01-01"
}

底層存儲格式

{
    "name":            [jack],
    "age":          [27],
    "join_date":      [2017-01-01],
    "address.country":         [china],
    "address.province":   [guangdong],
    "address.city":  [guangzhou]
}

對象數(shù)組:

{
    "authors": [
        { "age": 26, "name": "Jack White"},
        { "age": 55, "name": "Tom Jones"},
        { "age": 39, "name": "Kitty Smith"}
    ]
}

存儲格式:

{
    "authors.age":    [26, 55, 39],
    "authors.name":   [jack, white, tom, jones, kitty, smith]
}

2.0 數(shù)據(jù)建模

20180901144437612.png
20180901144234453.png

以下的索引 Mapping中,_source設置為false槽畔,同時各個字段的store根據(jù)需求設置了true和false栈妆。
url的doc_values設置為false,該字段url不用于聚合和排序操作。

PUT blog_index
{
  "mappings": {
    "doc": {
      "_source": {
        "enabled": false
      },
      "properties": {
        "title": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 100
            }
          },
          "store": true
        },
        "publish_date": {
          "type": "date",
          "store": true
        },
        "author": {
          "type": "keyword",
          "ignore_above": 100, 
          "store": true
        },
        "abstract": {
          "type": "text",
          "store": true
        },
        "content": {
          "type": "text",
          "store": true
        },
        "url": {
          "type": "keyword",
          "doc_values":false,
          "norms":false,
          "ignore_above": 100, 
          "store": true
        }
      }
    }
  }
}

ES多表關聯(lián)

目前ES主要有以下4種常用的方法來處理數(shù)據(jù)實體間的關聯(lián)關系:

(1)Application-side joins(服務端Join或客戶端Join)
這種方式鳞尔,索引之間完全獨立(利于對數(shù)據(jù)進行標準化處理嬉橙,如便于上述兩種增量同步的實現(xiàn)),由應用端的多次查詢來實現(xiàn)近似關聯(lián)關系查詢寥假。這種方法適用于第一個實體只有少量的文檔記錄的情況(使用ES的terms查詢具有上限市框,默認1024,具體可在elasticsearch.yml中修改)糕韧,并且最好它們很少改變枫振。這將允許應用程序對結果進行緩存,并避免經(jīng)常運行第一次查詢兔沃。

(2)Data denormalization(數(shù)據(jù)的非規(guī)范化)
這種方式蒋得,通俗點就是通過字段冗余,以一張大寬表來實現(xiàn)粗粒度的index乒疏,這樣可以充分發(fā)揮扁平化的優(yōu)勢额衙。但是這是以犧牲索引性能及靈活度為代價的。使用的前提:冗余的字段應該是很少改變的怕吴;比較適合與一對少量關系的處理窍侧。當業(yè)務數(shù)據(jù)庫并非采用非規(guī)范化設計時,這時要將數(shù)據(jù)同步到作為二級索引庫的ES中转绷,就很難使用上述增量同步方案伟件,必須進行定制化開發(fā),基于特定業(yè)務進行應用開發(fā)來處理join關聯(lián)和實體拼接议经。

ps:寬表處理在處理一對多斧账、多對多關系時,會有字段冗余問題煞肾,適合“一對少量”且這個“一”更新不頻繁的應用場景咧织。寬表化處理,在查詢階段如果只需要“一”這部分時籍救,需要進行結果去重處理(可以使用ES5.x的字段折疊特性习绢,但無法準確獲取分頁總數(shù),產(chǎn)品設計上需采用上拉加載分頁方式)

(3)Nested objects(嵌套文檔)
索引性能和查詢性能二者不可兼得蝙昙,必須進行取舍闪萄。嵌套文檔將實體關系嵌套組合在單文檔內部(類似與json的一對多層級結構),這種方式犧牲索引性能(文檔內任一屬性變化都需要重新索引該文檔)來換取查詢性能奇颠,可以同時返回關系實體败去,比較適合于一對少量的關系處理。
ps: 當使用嵌套文檔時烈拒,使用通用的查詢方式是無法訪問到的圆裕,必須使用合適的查詢方式(nested query三椿、nested filter、nested facet等)葫辐,很多場景下搜锰,使用嵌套文檔的復雜度在于索引階段對關聯(lián)關系的組織拼裝。

(4)Parent/child relationships(父子文檔)
父子文檔犧牲了一定的查詢性能來換取索引性能耿战,適用于一對多的關系處理蛋叼。其通過兩種type的文檔來表示父子實體,父子文檔的索引是獨立的剂陡。父-子文檔ID映射存儲在 Doc Values 中狈涮。當映射完全在內存中時, Doc Values 提供對映射的快速處理能力鸭栖,另一方面當映射非常大時歌馍,可以通過溢出到磁盤提供足夠的擴展能力。 在查詢parent-child替代方案時晕鹊,發(fā)現(xiàn)了一種filter-terms的語法松却,要求某一字段里有關聯(lián)實體的ID列表〗埃基本的原理是在terms的時候晓锻,對于多項取值,如果在另外的index或者type里已知主鍵id的情況下飞几,某一字段有這些值砚哆,可以直接嵌套查詢。具體可參考官方文檔的示例:通過用戶里的粉絲關系屑墨,微博和用戶的關系躁锁,來查詢某個用戶的粉絲發(fā)表的微博列表。
ps:父子文檔相比嵌套文檔較靈活卵史,但只適用于“一對大量”且這個“一”不是海量的應用場景战转,該方式比較耗內存和CPU,這種方式查詢比嵌套方式慢5~10倍程腹,且需要使用特定的has_parent和has_child過濾器查詢語法匣吊,查詢結果不能同時返回父子文檔(一次join查詢只能返回一種類型的文檔)儒拂。而受限于父子文檔必須在同一分片上寸潦,ES父子文檔在滾動索引、多索引場景下對父子關系存儲和聯(lián)合查詢支持得不好社痛,而且子文檔type刪除比較麻煩(子文檔刪除必須提供父文檔ID)见转。

如果業(yè)務端對查詢性能要求很高的話,還是建議使用寬表化處理*的方式蒜哀,這樣也可以比較好地應對聚合的需求斩箫。在索引階段需要做join處理,查詢階段可能需要做去重處理,分頁方式可能也得權衡考慮下乘客。

對比 Nested Object Parent/Child
優(yōu)點 文檔存儲在一塊狐血,讀取性能高 父子文檔獨立更新,互不影響
缺點 更新父或子文檔時需要更新整個文檔 為了維護join的關系易核,需要占用內存匈织,讀取性能較差
場景 子文檔偶爾更新,查詢頻繁 子文檔頻繁更新
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末牡直,一起剝皮案震驚了整個濱河市缀匕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碰逸,老刑警劉巖乡小,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異饵史,居然都是意外死亡满钟,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門胳喷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來零远,“玉大人,你說我怎么就攤上這事厌蔽∏@保” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵奴饮,是天一觀的道長纬向。 經(jīng)常有香客問我,道長戴卜,這世上最難降的妖魔是什么逾条? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮投剥,結果婚禮上师脂,老公的妹妹穿的比我還像新娘。我一直安慰自己江锨,他們只是感情好吃警,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著啄育,像睡著了一般酌心。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上挑豌,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天安券,我揣著相機與錄音墩崩,去河邊找鬼。 笑死侯勉,一個胖子當著我的面吹牛鹦筹,可吹牛的內容都是我干的。 我是一名探鬼主播址貌,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼盛龄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了芳誓?” 一聲冷哼從身側響起余舶,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锹淌,沒想到半個月后匿值,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡赂摆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年挟憔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烟号。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡绊谭,死狀恐怖,靈堂內的尸體忽然破棺而出汪拥,到底是詐尸還是另有隱情达传,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布迫筑,位于F島的核電站宪赶,受9級特大地震影響,放射性物質發(fā)生泄漏脯燃。R本人自食惡果不足惜搂妻,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辕棚。 院中可真熱鬧欲主,春花似錦、人聲如沸逝嚎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懈糯。三九已至涤妒,卻和暖如春单雾,著一層夾襖步出監(jiān)牢的瞬間赚哗,已是汗流浹背她紫。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留屿储,地道東北人贿讹。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像够掠,于是被迫代替她去往敵國和親民褂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內容