Elasticsearch學(xué)習(xí)筆記(11) - Mapping及自定義Analyzer

Elasticsearch的Mapping,定義了索引的結(jié)構(gòu),類似于關(guān)系型數(shù)據(jù)庫(kù)的Schema。Elasticsearch的Setting主要是為了定義搜索的最關(guān)鍵組件,即:Analyzer,也就是分析器。

Dynamic Mapping及常用字段類型

Mapping的定義

Mapping類似于關(guān)系型數(shù)據(jù)庫(kù)的Schema,主要包含以下內(nèi)容:

  1. 定義索引中字段的名稱
  2. 定義字段的數(shù)據(jù)類型,如:字符串、數(shù)字、boolean等
  3. 可對(duì)字段設(shè)置倒排索引的相關(guān)配置,如是否需要分詞,使用什么分詞器

從7.x開(kāi)始,一個(gè)Mapping只屬于一個(gè)索引的type

  1. 每個(gè)文檔屬于一個(gè)type
  2. 一個(gè)type有且僅有一個(gè)Mapping定義
  3. 從7.x開(kāi)始,不需要在Mapping中指定type信息,默認(rèn)type為_doc

常用字段類型

在Elasticsearch中,字段數(shù)據(jù)類型有以下常用的類型:

  1. 簡(jiǎn)單類型
    • Text / Keyword - 文本 / 關(guān)鍵字
    • Date - 日期
    • Integer / Float - 數(shù)字 / 浮點(diǎn)
    • Boolean - 布爾值
    • IPv4 / IPv6 - ip地址
  2. 復(fù)雜類型,包括對(duì)象和數(shù)組
    • 對(duì)象
    • 數(shù)組
  3. 特殊類型,如地理信息
    • geo_point / ...

動(dòng)態(tài)Mapping

動(dòng)態(tài)Mapping,英文名為Dynamic Mapping。

  1. 在寫(xiě)入文檔時(shí),如果索引不存在,會(huì)自動(dòng)創(chuàng)建索引
  2. 這種機(jī)制,使得我們無(wú)需手動(dòng)定義mappings。Elasticsearch會(huì)自動(dòng)根據(jù)文檔信息,推算出字段的類型
  3. 有的時(shí)候,Elasticsearch可能會(huì)推算不對(duì),如:地理位置信息
  4. 當(dāng)類型推算得不對(duì)時(shí),可能導(dǎo)致一些功能無(wú)法正常運(yùn)行,如Range查詢。

常用類型的自動(dòng)識(shí)別規(guī)則

類型 規(guī)則
字符串 匹配到日期格式,設(shè)置成Date。
字符串為數(shù)字時(shí),當(dāng)成字符串處理,但我們?cè)O(shè)置轉(zhuǎn)換為數(shù)字。
其他情況,類型就是Text,并且會(huì)增加keyword的子字段
布爾值 Boolean
浮點(diǎn)數(shù) Float
整數(shù) Long
對(duì)象 Object
數(shù)組 由第一個(gè)非空數(shù)值的類型決定
空值 忽略
# 寫(xiě)入文檔,查看 Mapping
PUT mapping_test/_doc/1
{
  "firstName": "Chan", -- Text
  "lastName":  "Jackie", -- Text
  "loginDate": "2018-07-24T10:29:48.103Z" -- Date
}

# Dynamic Mapping,推斷字段的類型
PUT mapping_test/_doc/1
{
    "uid": "123", -- Text
    "isVip": false, -- Boolean
    "isAdmin": "true", -- Text
    "age": 19, -- Long
    "heigh": 180 -- Long
}

# 查看 Dynamic Mapping
GET mapping_test/_mapping

字段類型是否可修改

  1. 新增加的字段
    • dynamic設(shè)為true時(shí),新增字段的文檔寫(xiě)入時(shí),Mapping同時(shí)被更新
    • dynamic設(shè)為false時(shí),Mapping不會(huì)被更新,新增字段的數(shù)據(jù)無(wú)法被索引,但是會(huì)出現(xiàn)在_source中
    • dynamic設(shè)為strict,文檔將寫(xiě)入失敗
  2. 已存在的字段,一旦數(shù)據(jù)被寫(xiě)入,就不再支持修改字段定義
    • Lucene本身的限制
  3. 如果希望更改字段類型,必須Reindex api,即:重建索引。在數(shù)據(jù)量多的時(shí)候,開(kāi)銷將非常大
# dynamic設(shè)置為false
PUT idx1
{
    "mapping": {
        "_doc": {
            "dynamic": "false"
        }
    }
}

# 修改為dynamic為false
PUT idx1/_mapping
{
  "dynamic": false
}

# 查看索引
GET idx1/_mapping

dynamic屬性和索引字段可變性的規(guī)則,我們可以總結(jié)如下:

\ true false strict
文檔可索引 yes yes no
字段可索引 yes no no
Mapping被更新 yes no no

顯式Mapping及常見(jiàn)參數(shù)

在本文的上一段落,我們的Mapping都是自動(dòng)生成的。自動(dòng)生成機(jī)制雖然方便,但是也可能導(dǎo)致一些問(wèn)題。比如:生成的字段類型不正確,字段的附加屬性不滿足我們的需求,等等。這時(shí),我們可以通過(guò)顯式Mapping的方式來(lái)解決。

那么,我們?nèi)绾芜M(jìn)行顯式Mapping的設(shè)置呢?

  1. 參考官網(wǎng)api,純手寫(xiě)
  2. 為減少工作量,減少出錯(cuò)概率,可如下進(jìn)行:
    1. 創(chuàng)建一個(gè)臨時(shí)index,寫(xiě)入一些樣本數(shù)據(jù)
    2. 通過(guò)訪問(wèn)Mapping API獲取該臨時(shí)文件的動(dòng)態(tài)Mapping定義
    3. 修改后,再使用此配置創(chuàng)建自己的索引
    4. 刪除臨時(shí)索引

我們推薦使用第二種方式,效率高,且不容易出錯(cuò)。

常見(jiàn)參數(shù) - index

index,可用于設(shè)置字段是否被索引,默認(rèn)為true,false即為不可搜索。在下述例子中,mobile字段將不能被搜索到。

# 設(shè)置 index 為 false
DELETE users
PUT users
{
    "mappings" : {
      "properties" : {
        "firstName" : {
          "type" : "text"
        },
        "lastName" : {
          "type" : "text"
        },
        "mobile" : {
          "type" : "text",
          "index": false
        }
      }
    }
}

常見(jiàn)參數(shù) - index_options

記錄索引級(jí)別。Text類型默認(rèn)為positions,其他類型默認(rèn)為docs。我們需要記住一條準(zhǔn)則。

記錄的內(nèi)容越多,占用的存儲(chǔ)空間就越大。

索引級(jí)別有以下幾種,更細(xì)節(jié)的內(nèi)容可參考【官網(wǎng)索引級(jí)別】

  1. docs
  2. freqs
  3. positions
  4. offsets

常見(jiàn)參數(shù) - null_value

需要對(duì)Null值實(shí)現(xiàn)搜索時(shí)使用。只有keyword類型才支持設(shè)定null_value

# 設(shè)定Null_value
DELETE users
PUT users
{
    "mappings" : {
      "properties" : {
        "firstName" : {
          "type" : "text"
        },
        "lastName" : {
          "type" : "text"
        },
        "mobile" : {
          "type" : "keyword",
          "null_value": "NULL"
        }
      }
    }
}

PUT users/_doc/1
{
  "firstName":"Zhang",
  "lastName": "Fubing",
  "mobile": null
}

PUT users/_doc/2
{
  "firstName":"Zhang",
  "lastName": "Fubing2"
}

# 查看結(jié)果,有且僅有_id為2的記錄
GET users/_search
{
  "query": {
    "match": {
      "mobile":"NULL"
    }
  }
}

常見(jiàn)參數(shù) - copy_to

這個(gè)屬性用于將當(dāng)前字段拷貝到指定字段。

  1. _all在7.x版本已經(jīng)被copy_to所代替
  2. 可用于滿足特定場(chǎng)景
  3. copy_to將字段數(shù)值拷貝到目標(biāo)字段,實(shí)現(xiàn)類似_all的作用
  4. copy_to的目標(biāo)字段不出現(xiàn)在_source中
# 設(shè)置 Copy to
DELETE users
PUT users
{
  "mappings": {
    "properties": {
      "firstName":{
        "type": "text",
        "copy_to": "fullName"
      },
      "lastName":{
        "type": "text",
        "copy_to": "fullName"
      }
    }
  }
}
PUT users/_doc/1
{
  "firstName":"Zhang",
  "lastName": "Fubing"
}

GET users/_search?q=fullName:(Zhang Fubing)

特殊的數(shù)組類型

Elasticsearch不提供專門的數(shù)組類型。但任何字段,都可以包含多個(gè)相同類型的數(shù)值。

# 數(shù)組類型
PUT users/_doc/1
{
  "name":"onebird",
  "interests":"reading"
}

PUT users/_doc/1
{
  "name":"twobirds",
  "interests":["reading","music"]
}

POST users/_search
{
  "query": {
        "match_all": {}
    }
}

# interests字段還是text類型
GET users/_mapping

多字段類型及自定義Analyzer

多字段類型

所謂多字段類型,即:一個(gè)字段可以有多個(gè)子字段。這種特性帶來(lái)了以下好處。

  1. 增加一個(gè)keyword子字段,可用于精確匹配
  2. 可對(duì)子字段設(shè)置不同的analyzer
    1. 不通語(yǔ)言的支持
    2. 可對(duì)中文拼音字段進(jìn)行搜索
    3. 可對(duì)搜索和索引指定不同的Analyzer

精確值和全文本

精確值(Exact Values) vs 全文本(Full Text)

  1. 精確值,包括數(shù)字、日期、具體的字符串(如“192.168.0.1”)
    • Elasticsearch中類型為keyword,索引時(shí),不需要做特殊的分詞處理
  2. 全文本,非結(jié)構(gòu)化的文本數(shù)據(jù)
    • Elasticsearch中類型為text,索引時(shí),需要對(duì)其進(jìn)行分詞處理

如下結(jié)構(gòu)的數(shù)據(jù),我們可以大致判斷出哪些是精確值,哪些是全文本。其中的200、info、debug都是精確值。而message的內(nèi)容為全文本。

{
    "code": 200,
    "message": "this is a error item, you can change your apollo config !",
    "content": {
        "tags": [
            "info",
            "debug"
        ]
    }
}

自定義分詞器

自定義分詞器,可通過(guò)組合不同的Character Filter、TokenizerToken Filter來(lái)實(shí)現(xiàn)。

Character Filter,常用的字符過(guò)濾器包括:

類型 作用
html strip 去除html
mapping 字符串替換
pattern replace 正則匹配替換

Tokenizer,用于將原始文本按照一定規(guī)則切分為詞(Term或Token)。我們除了使用Elasticsearch自動(dòng)的分詞器外,還可以自己通過(guò)開(kāi)發(fā)插件的方式來(lái)實(shí)現(xiàn)。常用的分詞器包括:

  • whitespace
  • standard
  • uax_url_email
  • pattern
  • keyword
  • path
  • hierarchy

Token Filter,分詞過(guò)濾器。主要用于對(duì)輸出的單詞,進(jìn)行增刪改。常用的分詞過(guò)濾器包括:

類型 作用
lowercase 轉(zhuǎn)換為小寫(xiě)
stop 去掉the、a、an等單詞
synonym 轉(zhuǎn)換為近義詞

在下面的例子中,我們實(shí)現(xiàn)了一個(gè)自定義分詞器。

# 編寫(xiě)自定義分析器
PUT index1
{
    "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_"
                }
            }
        }
    }
}

# 查看自定義分析器的效果
POST index1/_analyze
{
    "analyzer": "my_custom_analyzer",
    "text": "I'm a :) person, and you?"
}

總結(jié)

通過(guò)這篇文章,我們了解了Mapping的作用及常用字段類型,也知道了動(dòng)態(tài)Mapping和顯式Mapping的區(qū)別。另外,我們還了解了Mapping的多字段特性,以及如何自定義一個(gè)Analyzer。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容