Elasticsearch入門(3)-mapping
前言
掘友們好久不見,在之前的文章中,我們瞭解到了elasticsearch的查詢相關操作方法和一些原理,本章節將帶來elasticsearch的mapping詳細配置和用法,主要分為
- dynamic mapping機制
- 顯示mapping和相關引數
- 多欄位特性及mapping中自定義analyzer
Dynamic mapping
mapping
- mapping類似於資料庫中的schema的定義,作用如下
- 定義索引中的欄位的名稱
- 定義欄位的資料型別,例如字串,數字,布林
- 欄位,倒排索引的相關配置(Analyzed or Not Analyzed,Analyzer)
- Mapping會把JSON檔案對映成Lucene所需要的扁平格式
- 一個Mapping屬於一個索引的Type
- 每個檔案都屬於一個Type
- 一個Type有一個Mapping定義
- 7.0開始,不需要在Mapping定義中指定Type資訊
1. 是什麼
- 在寫入檔案時候,如果索引不存在,會自動建立索引
- Dynamic Mapping的機制,使得我們無需手動定義Mappings.Elasticsearch會根據檔案資訊,推算出欄位的型別
- 會遇到推算的不對的情況,例如地理位置資訊
- 當型別設定不對時,會導致一些功能無法正常執行,例如Range查詢
# 檢視Mapping,get ${indexname}/_mappings
GET movies/_mappings
複製程式碼
2. 型別的自動識別
JSON型別 | Elasticsearch |
---|---|
字串 | 匹配成日期格式,設定成Date 配置數字設定為float或long,該選項預設關閉 設定為text,並且增加keyword子欄位 |
布林值 | boolean |
浮點數 | float |
整數 | long |
物件 | Object |
陣列 | 由第一個非空數值的型別所決定 |
空值 | 忽略 |
demo
# dynamic mapping 推斷欄位的型別
PUT mapping_test/_doc/1
{
"uid":"123","isVip":false,"isAdmin":"true","age":19,"height":"183"
}
# 檢視Mapping檔案,檢視mapping推算
GET mapping_test/_mapping
複製程式碼
檢視結果如圖,我們可以發現es對輸入的json進行了相應的型別轉換
3. 更改Mapping的欄位型別
- 兩種情況下能夠修改
- 新增加欄位
- Dynamic 設定為true時,一旦有新增欄位的檔案寫入,Mapping也同時被更新
- Dynamic設為false,當有新的檔案加入,並且新的檔案包含新的欄位,Mapping不會被更新,意味著新增欄位的資料無法被索引,但是資訊會出現在_source中
- Dynamic設定為Strict,檔案寫入失敗
- 對已有欄位,一旦已有資料寫入,就不再支援修改欄位定義
- es基於Lucene實現的倒排索引,一旦生成後,就不允許修改
- 如果希望改變欄位型別,必須Reindex API,重建索引
- 新增加欄位
- 原因
- 如果修改了欄位的資料型別,會導致已被索引的屬於無法被搜尋
- 對於新增欄位,不存在該影響(新增欄位時建立新欄位索引)
4. 控制Dynamic mappings
dynamic設定對應功能
“true" | "false" | "strict" | |
---|---|---|---|
檔案可索引 | √ | √ | × |
欄位可索引 | √ | × | × |
Mapping被更新 | √ | × | × |
- 當dynamic被設定為false時候,存在新增欄位的資料寫入,該資料可以被索引,但是新增欄位被丟棄
- 當設定為Strict模式時候,資料寫入直接出錯
4.1 true
檔案可索引,欄位可索引,mapping被更新
# 預設mapping支援dynamic,寫入的檔案中加入新的欄位
PUT dynamic_mapping_test/_doc/1
{
"newFileld":"someValue"
}
# 搜尋
POST dynamic_mapping_test/_search
{
"query": {
"match": {
"newFileld": "someValue"
}
}
}
GET dynamic_mapping_test/_mapping
複製程式碼
4.2 false
檔案可索引,欄位不可索引,mapping不更新
# 修改dynamic false
PUT dynamic_mapping_test/_mapping
{
"dynamic":"false"
}
# 新增 anotherField
PUT dynamic_mapping_test/_doc/2
{
"anotherField":"anotherValue"
}
# 新增的欄位不可以被搜尋,因為dynamic已經被設定為false
POST dynamic_mapping_test/_search
{
"query": {
"match": {
"anotherField": "anotherValue"
}
}
}
複製程式碼
# mapping檔案查詢
GET dynamic_mapping_test/_mapping
複製程式碼
4.3 strict
檔案不可索引,欄位不可索引,mapping不更新
# 修改為strict
PUT dynamic_mapping_test/_mapping
{
"dynamic":"strict"
}
# 寫入資料,http code 400
PUT dynamic_mapping_test/_doc/3
{
"lastField":"lastValue"
}
複製程式碼
顯示mapping和引數介紹
1. 如何顯示定義
PUT docName
{
“mapping”:{
# define your mapping here
}
}
複製程式碼
2. 自定義mapping的建議
- 可以參考API手冊,純手寫
- 為了減少輸入的工作量,減少出錯概率,可以依照以下步驟
- 建立一個臨時的index,寫入一些樣本資料
- 通過訪問Mapping API獲得該臨時檔案的動態Mapping定義
- 修改後使用,參考該配置建立自己的索引
- 刪除臨時索引
3. index
- Index屬性:控制當前欄位是否被索引,預設為true,如果設定為false,欄位不可被索引
PUT users
{
"mappings":{
"properties":{
"firstName":{
"type":"text"
},"lastName":{
"type":"text"
},"mobile":{
"type":"text","index":false
}
}
}
}
複製程式碼
4. Index Options
對於倒排索引的建立,es提供了四種配置
- 四種不同級別的Index Options配置,可以控制倒排索引記錄的內容
- docs - 記錄doc id
- freqs - 記錄doc id和term frequencies
- positions - 記錄doc id / term frequencies / term postion
- offsets - 記錄 doc id / term frequencies / term position / character offsets
- Text 型別預設記錄positions,其他預設為docs
- 記錄內容越多,佔用儲存空間越大
5. null_value
有些時候插入的欄位時null,如果需要對Null值實現搜素,可以在mapping檔案中將“null_value”指定為“NULL”
GET users/_search?q=mobile:NULL
PUT users
{
"mappings":{
"properties":{
"firstName":{
"type":"text"
},"lastName":{
"type":"text"
},"mobile":{
"type":"keyword","null_value": "NULL"
}
}
}
}
複製程式碼
注意:
- 只有Keyword型別支援Null_Value
6. copy_to設定
_all在es7中已被廢棄,如要實現 _all 的功能,可用copy_to所替代
# 這個設定的意思就是說,你在索引一個檔案時候,它如果包含了firstName和lastName,都會把值拷貝到fullName上,當需要查詢的時候,就可以用fullName查詢了
PUT users
{
"mappings":{
"properties":{
"firstName":{
"type":"text","copy_to": "fullName"
},"lastName":{
"type":"text","copy_to": "fullName"
}
}
}
}
複製程式碼
查詢時:GET users/_search?q=fullName:(Jack Ma)
特點:
- 能滿足一些特定的搜尋需求
- copy_to將欄位的數值拷貝到目標欄位,實現類似_all的作用
- copy_to的目標欄位不出現在_source中
7. 陣列型別
- Elasticsearch中不提供專門的陣列型別,但是任何欄位,都可以包含多個相同型別別的數值
PUT users/_doc/1
{
"name":"zhangsan","interests":"reading"
}
PUT users/_doc/2
{
"name":"lisi","interests":["reading","coding"]
}
複製程式碼
檢視mapping檔案,可發現interests型別依然是text
多欄位特性及Mapping中配置自定義Analyzer
1. 多欄位型別
比如一個預設的text欄位,es都會給它加上keyword欄位型別,但有時候會給特定欄位加上子欄位,指定analyzer
- 多欄位特性
- 廠商名字實現精確匹配
- 增加一個keyword欄位
- 使用不同的Analyzer
- 不同語音
- 拼音欄位的搜尋
- 支援為搜尋和索引指定不同的analyzer
- 廠商名字實現精確匹配
2. Exact value v.s Full Text
- Exact value
- 精確值,包括資料/日期/具體的一個字串(例如“Apple Store")
- Elasticsearch中的keyword
- Full Text
- 全文字,非結構化的文字資料
- Elasticsearch中的text
如圖,exact value箭頭標註的值,對待這種數值,很多情況下我們要將這種數值作為精確值來看待,不需要對它進行分詞。
但訊息中的message需要對它進行分詞處理,以查到一些關鍵詞
2.1 Exact Values不需要被分詞
在elasticsearch中,exact value不需要做分詞處理
-
Elasticsearch為每一個欄位建立一個倒排索引
- Exact Value在索引時,不需要做特殊的分詞處理
3. 自定義分詞
- 當Elasticsearch自帶的分詞器無法滿足時,可以自定義分詞器,通過自組合不同的元件實現
- Character Filter
- Tokenizer
- Token Filter
3.1 Character Filter
-
在Tokenizer之前對文字進行處理,例如增加刪除及替換字元,可以配置多個Character Filters,會影響倒排索引Tokenizer的positon和offset資訊
-
一些自帶的Character Filters
-
HTML strip - 去除html標籤
#剝除不必要的html標籤 POST _analyze { "tokenizer": "keyword","char_filter": ["html_strip"],"text":"<b>hello world</b>" } 複製程式碼
-
Mapping - 字串替換
# 使用char filter進行替換,將中劃線替換為下劃線 POST _analyze { "tokenizer": "standard","char_filter": [ { "type":"mapping","mappings":["- => _"] } ],"text":"123-456,I-test! test-990 555-789-1114" } # char filter替換表情符號,如把表情替換為單詞 POST _analyze { "tokenizer": "standard","mappings":[":) => happy",":( => sad"] } ],"text": ["I am felling :)","Felling :( today"] } 複製程式碼
-
Pattern replace - 正則匹配替換
# 正則方式替換,替換http GET _analyze { "tokenizer": "standard","char_filter": [ { "type":"pattern_replace","pattern":"http://(.*)","replacement":"$1" } ],"text": "http://www.elastic.co" } 複製程式碼
-
3.2 Tokenizer
-
將原始的文字按照一定的規則,切分為詞(term or token)
-
elasticsearch內建的Tokenizers包括
-
whitespace/standard/uax_url_email/pattern(正則)/keyword(不做處理,直接索引)/path hierarchy(路徑處理)
# tokenizer按照檔案路徑 POST _analyze { "tokenizer": "path_hierarchy","text": "/usr/jackMa/a/b/c/d/e" } 複製程式碼
-
-
可以用java開發外掛,實現自己的Tokenizer(期待後續試驗····)
3.3 Token filters
-
將Tokenizer輸出的單詞(term),進行增加,修改,刪除
-
自帶的Token Filters
-
Lowercase / stop / synonym(新增近義詞)
# TOKEN FILTERS # whitespace與stop,is去除 GET _analyze { "tokenizer": "whitespace","filter": ["stop"],"text": ["The stone is knocked"] } # remove 加入lowercase後,小寫處理,然後The被當成stopword刪除 GET _analyze { "tokenizer": "whitespace","filter": ["lowercase","stop"],"text": ["The man sitting on the Chair is my classmate!"] } 複製程式碼
-
3.4 設定一個custom Analyzer
建立索引時,定義custom Analyzer
#如何自定義Analyzer
# 先刪除之前建立的
DELETE my_index
# 可以在建立索引的時候指定setting,首先我們定義分詞器,其中的char_filter和tokenizer還有filter中的English_stop都是自定義的
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer":{
"type":"custom","char_filter":["emoticons"],"tokenizer":"punctuation","filter":[
"lowercase","english_stop"
]
}
},"tokenizer": {
"punctuation":{
"type":"pattern","pattern":"[ .,!?]"
}
},"char_filter": {
"emoticons":{
"type":"mapping","mappings":[
":) => _happy_",":( => _sad_"
]
}
},"filter": {
"english_stop":{
"type":"stop","stopwords":"_english_"
}
}
}
}
}
複製程式碼
針對建立的analyzer進行測試
# 測試自定義的analyzer
POST my_index/_analyze
{
"analyzer": "my_custom_analyzer","text":"I'm a :) person,and you?"
}
複製程式碼
分詞結果:
3.4.1 方法論
自定義分析器標準格式是:
PUT /my_index
{
"settings": {
"analysis": {
"char_filter": { ... custom character filters ... },//字元過濾器
"tokenizer": { ... custom tokenizers ... },//分詞器
"filter": { ... custom token filters ... },//詞單元過濾器
"analyzer": { ... custom analyzers ... }
}
}
}
複製程式碼
例項:
PUT /my_index
{
"settings": {
"analysis": {
"char_filter": {
"&_to_and": {
"type": "mapping","mappings": [ "&=> and "]
}},"filter": {
"my_stopwords": {
"type": "stop","stopwords": [ "the","a" ]
}},"analyzer": {
"my_analyzer": {
"type": "custom","char_filter": [ "html_strip","&_to_and" ],"tokenizer": "standard","filter": [ "lowercase","my_stopwords" ]
}}
}}}
# 比如自定義好的analyzer名字是my_analyzer,在此索引下的某個新增欄位應用此分析器
PUT /my_index/_mapping
{
"properties":{
"username":{
"type":"text","analyzer" : "my_analyzer"
},"password" : {
"type" : "text"
}
}
}
# 插入資料
PUT /my_index/_doc/1
{
"username":"The quick & brown fox ","password":"The quick & brown fox "
}
# username採用自定義分析器my_analyzer,password採用預設的standard分析器
# 驗證
GET /index_v1/_analyze
{
"field":"username","text":"The quick & brown fox"
}
GET /index_v1/_analyze
{
"field":"password","text":"The quick & brown fox"
}
複製程式碼
小結
本篇對elasticsearch的mapping機制進行了大篇幅的介紹和講解,具體的程式碼部分不用宕機硬背,再實際操練時候,結合 Ctrl+/
的快捷鍵,可以快速檢視官網的檔案,互相結合,理解效率更高。
覺得不錯,請點個贊吧