@[toc]
ElasticSearch 系列教程我們前面已經(jīng)連著發(fā)了四篇了向拆,今天第五篇似芝,我們來聊一聊 Es 中的 23 種常見的映射參數(shù)蛹磺。
針對這 23 種常見的映射參數(shù)锹安,松哥專門錄制了一個(gè)視頻教程:
視頻鏈接: https://pan.baidu.com/s/1J23m6oSTeZJU6j6KaogZSg 提取碼: 6k2a
本文是松哥所錄視頻教程的一個(gè)筆記畅买,筆記簡明扼要并闲,完整內(nèi)容小伙伴們可以參考視頻。
1.ElasticSearch 映射參數(shù)
1.1 analyzer
定義文本字段的分詞器谷羞。默認(rèn)對索引和查詢都是有效的帝火。
假設(shè)不用分詞器,我們先來看一下索引的結(jié)果洒宝,創(chuàng)建一個(gè)索引并添加一個(gè)文檔:
PUT blog
PUT blog/_doc/1
{
"title":"定義文本字段的分詞器购公。默認(rèn)對索引和查詢都是有效的。"
}
查看詞條向量(term vectors)
GET blog/_termvectors/1
{
"fields": ["title"]
}
查看結(jié)果如下:
{
"_index" : "blog",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"found" : true,
"took" : 0,
"term_vectors" : {
"title" : {
"field_statistics" : {
"sum_doc_freq" : 22,
"doc_count" : 1,
"sum_ttf" : 23
},
"terms" : {
"義" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 1,
"start_offset" : 1,
"end_offset" : 2
}
]
},
"分" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 7,
"start_offset" : 7,
"end_offset" : 8
}
]
},
"和" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 15,
"start_offset" : 16,
"end_offset" : 17
}
]
},
"器" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 9,
"start_offset" : 9,
"end_offset" : 10
}
]
},
"字" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 4,
"start_offset" : 4,
"end_offset" : 5
}
]
},
"定" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 0,
"start_offset" : 0,
"end_offset" : 1
}
]
},
"對" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 12,
"start_offset" : 13,
"end_offset" : 14
}
]
},
"引" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 14,
"start_offset" : 15,
"end_offset" : 16
}
]
},
"效" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 21,
"start_offset" : 22,
"end_offset" : 23
}
]
},
"文" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 2,
"start_offset" : 2,
"end_offset" : 3
}
]
},
"是" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 19,
"start_offset" : 20,
"end_offset" : 21
}
]
},
"有" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 20,
"start_offset" : 21,
"end_offset" : 22
}
]
},
"本" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 3,
"start_offset" : 3,
"end_offset" : 4
}
]
},
"查" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 16,
"start_offset" : 17,
"end_offset" : 18
}
]
},
"段" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 5,
"start_offset" : 5,
"end_offset" : 6
}
]
},
"的" : {
"term_freq" : 2,
"tokens" : [
{
"position" : 6,
"start_offset" : 6,
"end_offset" : 7
},
{
"position" : 22,
"start_offset" : 23,
"end_offset" : 24
}
]
},
"索" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 13,
"start_offset" : 14,
"end_offset" : 15
}
]
},
"認(rèn)" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 11,
"start_offset" : 12,
"end_offset" : 13
}
]
},
"詞" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 8,
"start_offset" : 8,
"end_offset" : 9
}
]
},
"詢" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 17,
"start_offset" : 18,
"end_offset" : 19
}
]
},
"都" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 18,
"start_offset" : 19,
"end_offset" : 20
}
]
},
"默" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 10,
"start_offset" : 11,
"end_offset" : 12
}
]
}
}
}
}
}
可以看到雁歌,默認(rèn)情況下宏浩,中文就是一個(gè)字一個(gè)字的分,這種分詞方式?jīng)]有任何意義靠瞎。如果這樣分詞比庄,查詢就只能按照一個(gè)字一個(gè)字來查,像下面這樣:
GET blog/_search
{
"query": {
"term": {
"title": "定"
}
}
}
無意義7ρ巍<岩ぁ!
所以父能,我們要根據(jù)實(shí)際情況神凑,配置合適的分詞器。
給字段設(shè)定分詞器:
PUT blog
{
"mappings": {
"properties": {
"title":{
"type":"text",
"analyzer": "ik_smart"
}
}
}
}
存儲(chǔ)文檔:
PUT blog/_doc/1
{
"title":"定義文本字段的分詞器。默認(rèn)對索引和查詢都是有效的溉委。"
}
查看詞條向量:
GET blog/_termvectors/1
{
"fields": ["title"]
}
查詢結(jié)果如下:
{
"_index" : "blog",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"found" : true,
"took" : 1,
"term_vectors" : {
"title" : {
"field_statistics" : {
"sum_doc_freq" : 12,
"doc_count" : 1,
"sum_ttf" : 13
},
"terms" : {
"分詞器" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 4,
"start_offset" : 7,
"end_offset" : 10
}
]
},
"和" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 8,
"start_offset" : 16,
"end_offset" : 17
}
]
},
"字段" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 2,
"start_offset" : 4,
"end_offset" : 6
}
]
},
"定義" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 0,
"start_offset" : 0,
"end_offset" : 2
}
]
},
"對" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 6,
"start_offset" : 13,
"end_offset" : 14
}
]
},
"文本" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 1,
"start_offset" : 2,
"end_offset" : 4
}
]
},
"有效" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 11,
"start_offset" : 21,
"end_offset" : 23
}
]
},
"查詢" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 9,
"start_offset" : 17,
"end_offset" : 19
}
]
},
"的" : {
"term_freq" : 2,
"tokens" : [
{
"position" : 3,
"start_offset" : 6,
"end_offset" : 7
},
{
"position" : 12,
"start_offset" : 23,
"end_offset" : 24
}
]
},
"索引" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 7,
"start_offset" : 14,
"end_offset" : 16
}
]
},
"都是" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 10,
"start_offset" : 19,
"end_offset" : 21
}
]
},
"默認(rèn)" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 5,
"start_offset" : 11,
"end_offset" : 13
}
]
}
}
}
}
}
然后就可以通過詞去搜索了:
GET blog/_search
{
"query": {
"term": {
"title": "索引"
}
}
}
1.2 search_analyzer
查詢時(shí)候的分詞器鹃唯。默認(rèn)情況下,如果沒有配置 search_analyzer瓣喊,則查詢時(shí)坡慌,首先查看有沒有 search_analyzer,有的話藻三,就用 search_analyzer 來進(jìn)行分詞洪橘,如果沒有,則看有沒有 analyzer棵帽,如果有熄求,則用 analyzer 來進(jìn)行分詞,否則使用 es 默認(rèn)的分詞器逗概。
1.3 normalizer
normalizer 參數(shù)用于解析前(索引或者查詢)的標(biāo)準(zhǔn)化配置抡四。
比如,在 es 中仗谆,對于一些我們不想切分的字符串,我們通常會(huì)將其設(shè)置為 keyword淑履,搜索時(shí)候也是使用整個(gè)詞進(jìn)行搜索隶垮。如果在索引前沒有做好數(shù)據(jù)清洗,導(dǎo)致大小寫不一致秘噪,例如 javaboy 和 JAVABOY狸吞,此時(shí),我們就可以使用 normalizer 在索引之前以及查詢之前進(jìn)行文檔的標(biāo)準(zhǔn)化指煎。
先來一個(gè)反例蹋偏,創(chuàng)建一個(gè)名為 blog 的索引,設(shè)置 author 字段類型為 keyword:
PUT blog
{
"mappings": {
"properties": {
"author":{
"type": "keyword"
}
}
}
}
添加兩個(gè)文檔:
PUT blog/_doc/1
{
"author":"javaboy"
}
PUT blog/_doc/2
{
"author":"JAVABOY"
}
然后進(jìn)行搜索:
GET blog/_search
{
"query": {
"term": {
"author": "JAVABOY"
}
}
}
大寫關(guān)鍵字可以搜到大寫的文檔至壤,小寫關(guān)鍵字可以搜到小寫的文檔威始。
如果使用了 normalizer,可以在索引和查詢時(shí)像街,分別對文檔進(jìn)行預(yù)處理黎棠。
normalizer 定義方式如下:
PUT blog
{
"settings": {
"analysis": {
"normalizer":{
"my_normalizer":{
"type":"custom",
"filter":["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"author":{
"type": "keyword",
"normalizer":"my_normalizer"
}
}
}
}
在 settings 中定義 normalizer,然后在 mappings 中引用镰绎。
測試方式和前面一致脓斩。此時(shí)查詢的時(shí)候,大寫關(guān)鍵字也可以查詢到小寫文檔畴栖,因?yàn)闊o論是索引還是查詢随静,都會(huì)將大寫轉(zhuǎn)為小寫。
1.4 boost
boost 參數(shù)可以設(shè)置字段的權(quán)重吗讶。
boost 有兩種使用思路燎猛,一種就是在定義 mappings 的時(shí)候使用恋捆,在指定字段類型時(shí)使用;另一種就是在查詢時(shí)使用扛门。
實(shí)際開發(fā)中建議使用后者鸠信,前者有問題:如果不重新索引文檔,權(quán)重?zé)o法修改论寨。
mapping 中使用 boost(不推薦):
PUT blog
{
"mappings": {
"properties": {
"content":{
"type": "text",
"boost": 2
}
}
}
}
另一種方式就是在查詢的時(shí)候星立,指定 boost
GET blog/_search
{
"query": {
"match": {
"content": {
"query": "你好",
"boost": 2
}
}
}
}
1.5 coerce
coerce 用來清除臟數(shù)據(jù),默認(rèn)為 true葬凳。
例如一個(gè)數(shù)字绰垂,在 JSON 中,用戶可能寫錯(cuò)了:
{"age":"99"}
或者 :
{"age":"99.0"}
這些都不是正確的數(shù)字格式火焰。
通過 coerce 可以解決該問題劲装。
默認(rèn)情況下,以下操作沒問題昌简,就是 coerce 起作用:
PUT blog
{
"mappings": {
"properties": {
"age":{
"type": "integer"
}
}
}
}
POST blog/_doc
{
"age":"99.0"
}
如果需要修改 coerce 占业,方式如下:
PUT blog
{
"mappings": {
"properties": {
"age":{
"type": "integer",
"coerce": false
}
}
}
}
POST blog/_doc
{
"age":99
}
當(dāng) coerce 修改為 false 之后,數(shù)字就只能是數(shù)字了纯赎,不可以是字符串谦疾,該字段傳入字符串會(huì)報(bào)錯(cuò)。
1.6 copy_to
這個(gè)屬性犬金,可以將多個(gè)字段的值念恍,復(fù)制到同一個(gè)字段中。
定義方式如下:
PUT blog
{
"mappings": {
"properties": {
"title":{
"type": "text",
"copy_to": "full_content"
},
"content":{
"type": "text",
"copy_to": "full_content"
},
"full_content":{
"type": "text"
}
}
}
}
PUT blog/_doc/1
{
"title":"你好江南一點(diǎn)雨",
"content":"當(dāng) coerce 修改為 false 之后晚顷,數(shù)字就只能是數(shù)字了峰伙,不可以是字符串,該字段傳入字符串會(huì)報(bào)錯(cuò)该默。"
}
GET blog/_search
{
"query": {
"term": {
"full_content": "當(dāng)"
}
}
}
1.7 doc_values 和 fielddata
es 中的搜索主要是用到倒排索引瞳氓,doc_values 參數(shù)是為了加快排序、聚合操作而生的权均。當(dāng)建立倒排索引的時(shí)候顿膨,會(huì)額外增加列式存儲(chǔ)映射。
doc_values 默認(rèn)是開啟的叽赊,如果確定某個(gè)字段不需要排序或者不需要聚合恋沃,那么可以關(guān)閉 doc_values。
大部分的字段在索引時(shí)都會(huì)生成 doc_values必指,除了 text囊咏。text 字段在查詢時(shí)會(huì)生成一個(gè) fielddata 的數(shù)據(jù)結(jié)構(gòu),fieldata 在字段首次被聚合、排序的時(shí)候生成梅割。
doc_values | fielddata |
---|---|
索引時(shí)創(chuàng)建 | 使用時(shí)動(dòng)態(tài)創(chuàng)建 |
磁盤 | 內(nèi)存 |
不占用內(nèi)存 | 不占用磁盤 |
索引速度稍微低一點(diǎn) | 文檔很多時(shí)霜第,動(dòng)態(tài)創(chuàng)建慢,占內(nèi)存 |
doc_values 默認(rèn)開啟户辞,fielddata 默認(rèn)關(guān)閉泌类。
doc_values 演示:
PUT users
PUT users/_doc/1
{
"age":100
}
PUT users/_doc/2
{
"age":99
}
PUT users/_doc/3
{
"age":98
}
PUT users/_doc/4
{
"age":101
}
GET users/_search
{
"query": {
"match_all": {}
},
"sort":[
{
"age":{
"order": "desc"
}
}
]
}
由于 doc_values 默認(rèn)時(shí)開啟的,所以可以直接使用該字段排序底燎,如果想關(guān)閉 doc_values 刃榨,如下:
PUT users
{
"mappings": {
"properties": {
"age":{
"type": "integer",
"doc_values": false
}
}
}
}
PUT users/_doc/1
{
"age":100
}
PUT users/_doc/2
{
"age":99
}
PUT users/_doc/3
{
"age":98
}
PUT users/_doc/4
{
"age":101
}
GET users/_search
{
"query": {
"match_all": {}
},
"sort":[
{
"age":{
"order": "desc"
}
}
]
}
1.8 dynamic
1.9 enabled
es 默認(rèn)會(huì)索引所有的字段,但是有的字段可能只需要存儲(chǔ)双仍,不需要索引枢希。此時(shí)可以通過 enabled 字段來控制:
PUT blog
{
"mappings": {
"properties": {
"title":{
"enabled": false
}
}
}
}
PUT blog/_doc/1
{
"title":"javaboy"
}
GET blog/_search
{
"query": {
"term": {
"title": "javaboy"
}
}
}
設(shè)置了 enabled 為 false 之后,就可以再通過該字段進(jìn)行搜索了朱沃。
1.10 format
日期格式苞轿。format 可以規(guī)范日期格式,而且一次可以定義多個(gè) format逗物。
PUT users
{
"mappings": {
"properties": {
"birthday":{
"type": "date",
"format": "yyyy-MM-dd||yyyy-MM-dd HH:mm:ss"
}
}
}
}
PUT users/_doc/1
{
"birthday":"2020-11-11"
}
PUT users/_doc/2
{
"birthday":"2020-11-11 11:11:11"
}
- 多個(gè)日期格式之間搬卒,使用 || 符號連接,注意沒有空格翎卓。
- 如果用戶沒有指定日期的 format秀睛,默認(rèn)的日期格式是
strict_date_optional_time||epoch_mills
另外,所有的日期格式莲祸,可以在 https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html 網(wǎng)址查看。
1.11 ignore_above
igbore_above 用于指定分詞和索引的字符串最大長度椭迎,超過最大長度的話锐帜,該字段將不會(huì)被索引,這個(gè)字段只適用于 keyword 類型畜号。
PUT blog
{
"mappings": {
"properties": {
"title":{
"type": "keyword",
"ignore_above": 10
}
}
}
}
PUT blog/_doc/1
{
"title":"javaboy"
}
PUT blog/_doc/2
{
"title":"javaboyjavaboyjavaboy"
}
GET blog/_search
{
"query": {
"term": {
"title": "javaboyjavaboyjavaboy"
}
}
}
1.12 ignore_malformed
ignore_malformed 可以忽略不規(guī)則的數(shù)據(jù)缴阎,該參數(shù)默認(rèn)為 false。
PUT users
{
"mappings": {
"properties": {
"birthday":{
"type": "date",
"format": "yyyy-MM-dd||yyyy-MM-dd HH:mm:ss"
},
"age":{
"type": "integer",
"ignore_malformed": true
}
}
}
}
PUT users/_doc/1
{
"birthday":"2020-11-11",
"age":99
}
PUT users/_doc/2
{
"birthday":"2020-11-11 11:11:11",
"age":"abc"
}
PUT users/_doc/2
{
"birthday":"2020-11-11 11:11:11aaa",
"age":"abc"
}
1.13 include_in_all
這個(gè)是針對 _all
字段的简软,但是在 es7 中蛮拔,該字段已經(jīng)被廢棄了。
1.14 index
index 屬性指定一個(gè)字段是否被索引痹升,該屬性為 true 表示字段被索引建炫,false 表示字段不被索引。
PUT users
{
"mappings": {
"properties": {
"age":{
"type": "integer",
"index": false
}
}
}
}
PUT users/_doc/1
{
"age":99
}
GET users/_search
{
"query": {
"term": {
"age": 99
}
}
}
- 如果 index 為 false疼蛾,則不能通過對應(yīng)的字段搜索肛跌。
1.15 index_options
index_options 控制索引時(shí)哪些信息被存儲(chǔ)到倒排索引中(用在 text 字段中),有四種取值:
index_options | 備注 |
---|---|
docs | 只存儲(chǔ)文檔編號,默認(rèn)即此 |
freqs | 在 docs 基礎(chǔ)上衍慎,存儲(chǔ)詞項(xiàng)頻率 |
positions | 在 freqs 基礎(chǔ)上转唉,存儲(chǔ)詞項(xiàng)偏移位置 |
offsets | 在 positions 基礎(chǔ)上,存儲(chǔ)詞項(xiàng)開始和結(jié)束的字符位置 |
1.16 norms
norms 對字段評分有用稳捆,text 默認(rèn)開啟 norms赠法,如果不是特別需要肖爵,不要開啟 norms平斩。
1.17 null_value
在 es 中峭火,值為 null 的字段不索引也不可以被搜索掸冤,null_value 可以讓值為 null 的字段顯式的可索引驻呐、可搜索:
PUT users
{
"mappings": {
"properties": {
"name":{
"type": "keyword",
"null_value": "javaboy_null"
}
}
}
}
PUT users/_doc/1
{
"name":null,
"age":99
}
GET users/_search
{
"query": {
"term": {
"name": "javaboy_null"
}
}
}
1.18 position_increment_gap
被解析的 text 字段會(huì)將 term 的位置考慮進(jìn)去璃弄,目的是為了支持近似查詢和短語查詢肝断,當(dāng)我們?nèi)ニ饕粋€(gè)含有多個(gè)值的 text 字段時(shí)迂尝,會(huì)在各個(gè)值之間添加一個(gè)假想的空間鞠评,將值隔開茂蚓,這樣就可以有效避免一些無意義的短語匹配,間隙大小通過 position_increment_gap 來控制剃幌,默認(rèn)是 100聋涨。
PUT users
PUT users/_doc/1
{
"name":["zhang san","li si"]
}
GET users/_search
{
"query": {
"match_phrase": {
"name": {
"query": "sanli"
}
}
}
}
-
sanli
搜索不到,因?yàn)閮蓚€(gè)短語之間有一個(gè)假想的空隙负乡,為 100牍白。
GET users/_search
{
"query": {
"match_phrase": {
"name": {
"query": "san li",
"slop": 101
}
}
}
}
可以通過 slop 指定空隙大小。
也可以在定義索引的時(shí)候抖棘,指定空隙:
PUT users
{
"mappings": {
"properties": {
"name":{
"type": "text",
"position_increment_gap": 0
}
}
}
}
PUT users/_doc/1
{
"name":["zhang san","li si"]
}
GET users/_search
{
"query": {
"match_phrase": {
"name": {
"query": "san li"
}
}
}
}
1.19 properties
1.20 similarity
similarity 指定文檔的評分模型茂腥,默認(rèn)有三種:
similarity | 備注 |
---|---|
BM25 | es 和 lucene 默認(rèn)的評分模型 |
classic | TF/IDF 評分 |
boolean | boolean 模型評分 |
1.21 store
默認(rèn)情況下,字段會(huì)被索引切省,也可以搜索最岗,但是不會(huì)存儲(chǔ),雖然不會(huì)被存儲(chǔ)的朝捆,但是 _source
中有一個(gè)字段的備份般渡。如果想將字段存儲(chǔ)下來,可以通過配置 store 來實(shí)現(xiàn)芙盘。
1.22 term_vectors
term_vectors 是通過分詞器產(chǎn)生的信息驯用,包括:
- 一組 terms
- 每個(gè) term 的位置
- term 的首字符/尾字符與原始字符串原點(diǎn)的偏移量
term_vectors 取值:
取值 | 備注 |
---|---|
no | 不存儲(chǔ)信息,默認(rèn)即此 |
yes | term 被存儲(chǔ) |
with_positions | 在 yes 的基礎(chǔ)上增加位置信息 |
with_offset | 在 yes 的基礎(chǔ)上增加偏移信息 |
with_positions_offsets | term儒老、位置蝴乔、偏移量都存儲(chǔ) |
1.23 fields
fields 參數(shù)可以讓同一字段有多種不同的索引方式。例如:
PUT blog
{
"mappings": {
"properties": {
"title":{
"type": "text",
"fields": {
"raw":{
"type":"keyword"
}
}
}
}
}
}
PUT blog/_doc/1
{
"title":"javaboy"
}
GET blog/_search
{
"query": {
"term": {
"title.raw": "javaboy"
}
}
}
最后驮樊,松哥還搜集了 50+ 個(gè)項(xiàng)目需求文檔淘这,想做個(gè)項(xiàng)目練練手的小伙伴不妨看看哦~