一、背景知識
在Es中,字段的類型很關鍵:
- 在索引的時候,如果字段第一次出現,會自動識別某個類型,這種規則之前已經講過了。
- 那么如果一個字段已經存在了,並且設置為某個類型。再來一條數據,字段的數據不與當前的類型相符,就會出現字段沖突的問題。如果發生了沖突,在2.x版本會自動拒絕。
- 如果自動映射無法滿足需求,就需要使用者自己來設置映射類型,因此,就需要使用者了解ES中的類型。
下面就步入正題吧!
二、字段中的索引和存儲
其中需要說明的是:
1.index定義字段的分析類型以及檢索方式
- 如果是no,則無法通過檢索查詢到該字段;
- 如果設置為not_analyzed則會將整個字段存儲為關鍵詞,常用於漢字短語、郵箱等復雜的字符串;
- 如果設置為analyzed則將會通過默認的standard分析器進行分析,詳細的分析規則參考這里
2.store定義了字段是否存儲
在《ES IN ACTION》中有這樣一段描述:
This might be useful when you ask Elasticsearch for a particular field because retrieving a single stored field will be faster than retrieving the entire _source and extracting that field from it, especially when you have large documents. NOTE When you store individual fields as well, you should take into account that the more you store, the bigger your index gets. Usually bigger indices imply slower indexing and slower searching.
意思是,在ES中原始的文本會存儲在_source里面(除非你關閉了它)。默認情況下其他提取出來的字段都不是獨立存儲的,是從_source里面提取出來的。當然你也可以獨立的存儲某個字段,只要設置store:true即可。
獨立存儲某個字段,在頻繁使用某個特殊字段時很常用。而且獲取獨立存儲的字段要比從_source中解析快得多,而且額外你還需要從_source中解析出來這個字段,尤其是_source特別大的時候。
不過需要注意的是,獨立存儲的字段越多,那么索引就越大;索引越大,索引和檢索的過程就會越慢....
3.Text vs. keyword
ElasticSearch 5.0以后,string類型有重大變更,移除了string
類型,string
字段被拆分成兩種新的數據類型: text
用於全文搜索的,而keyword
用於關鍵詞搜索。
ElasticSearch對字符串擁有兩種完全不同的搜索方式. 你可以按照整個文本進行匹配, 即關鍵詞搜索(keyword search), 也可以按單個字符匹配, 即全文搜索(full-text search). 對ElasticSearch稍有了解的人都知道, 前者的字符串被稱為not-analyzed字符, 而后者被稱作analyzed字符串。
Text:會分詞,然后進行索引
支持模糊、精確查詢
不支持聚合
keyword:不進行分詞,直接索引
支持模糊、精確查詢
支持聚合
text用於全文搜索的, 而keyword用於關鍵詞搜索.
如果想做類似於sql中的like查詢,可定義為keyword並使用通配符wildcard方式查詢。
ElasticSearch字符串將默認被同時映射成text
和keyword
類型,將會自動創建下面的動態映射(dynamic mappings):
{ "foo": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } }
基於這個映射你即可以在foo字段上進行全文搜索, 也可以通過foo.keyword字段實現關鍵詞搜索及數據聚合.
禁用這個特性也很方便: 你只需要在定義mapping時顯式聲明字符串字段的類型或者使用一個動態模板(dynamic template)來匹配你所有的字符串字段即可. 例如通過下面的dynamic template就可以恢復到在ElasticSearch 2.x中使用的dynamic template的效果:
{ "match_mapping_type": "string", "mapping": { "type": "text" } }
4.Numeric
數值類型,注意numeric並不是一個類型,它包括多種類型,比如:long,integer,short,byte,double,float,每種的存儲空間都是不一樣的,一般默認推薦integer和float。官方文檔參考
重要的參數:
index分析
- not_analyzed(默認) ,設置為該值可以保證該字段能通過檢索查詢到
- no
store存儲
- true 獨立存儲
- false(默認)不存儲,從_source中解析
5.date
日期類型,該類型可以接受一些常見的日期表達方式,官方文檔參考。
重要的參數:
index分析
- not_analyzed(默認) ,設置為該值可以保證該字段能通過檢索查詢到
- no
store存儲
- true 獨立存儲
- false(默認)不存儲,從_source中解析
format格式化
- strict_date_optional_time||epoch_millis(默認)
- 你也可以自定義格式化內容,比如
"date": { "type": "date", "format": "yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" }
6.IP
這個類型可以用來標識IPV4的地址,參考官方文檔
常用參數:
index分析
- not_analyzed(默認) ,設置為該值可以保證該字段能通過檢索查詢到
- no
store存儲
- true 獨立存儲
- false(默認)不存儲,從_source中解析
7.boolean
布爾類型,所有的類型都可以標識布爾類型,參考官方文檔
- False: 表示該值的有:false, "false", "off", "no", "0", "" (empty string), 0, 0.0
- True: 所有非False的都是true
重要的參數:
index分析
- not_analyzed(默認) ,設置為該值可以保證該字段能通過檢索查詢到
- no
store存儲
- true 獨立存儲
- false(默認)不存儲,從_source中解析
三、內置分詞器
1.基本概念
全文搜索引擎會用某種算法對要建索引的文檔進行分析, 從文檔中提取出若干Token(詞元), 這些算法稱為Tokenizer(分詞器), 這些Token會被進一步處理, 比如轉成小寫等, 這些處理算法被稱為Token Filter(詞元處理器), 被處理后的結果被稱為Term(詞), 文檔中包含了幾個這樣的Term被稱為Frequency(詞頻)。 引擎會建立Term和原文檔的Inverted Index(倒排索引), 這樣就能根據Term很快到找到源文檔了。 文本被Tokenizer處理前可能要做一些預處理, 比如去掉里面的HTML標記, 這些處理的算法被稱為Character Filter(字符過濾器), 這整個的分析算法被稱為Analyzer(分析器)。
ES內置了很多Analyzer, 還有很多第三方的Analyzer插件, 比如一些處理中文的Analyzer(中文分詞)。
analyzer、 tokenizer、 filter可以在elasticsearch.yml 配置, 下面是配置例子
index : analysis : analyzer : standard : type : standard stopwords : [stop1, stop2] myAnalyzer1 : type : standard stopwords : [stop1, stop2, stop3] max_token_length : 500 # configure a custom analyzer which is # exactly like the default standard analyzer myAnalyzer2 : tokenizer : standard filter : [standard, lowercase, stop] tokenizer : myTokenizer1 : type : standard max_token_length : 900 myTokenizer2 : type : keyword buffer_size : 512 filter : myTokenFilter1 : type : stop stopwords : [stop1, stop2, stop3, stop4] myTokenFilter2 : type : length min : 0 max : 2000
2.組裝自己的analyzer
ES內置若干analyzer, 另外還可以用內置的character filter, tokenizer, token filter組裝一個analyzer(custom analyzer), 比如
index :
analysis :
analyzer :
myAnalyzer :
tokenizer : standard
filter : [standard, lowercase, stop]
3.使用第三方分詞器
如果你要使用第三方的analyzer插件,需要先在配置文件elasticsearch.yml中注冊, 下面是配置IkAnalyzer的例子
index:
analysis:
analyzer:
ik:
alias: [ik_analyzer]
type: org.elasticsearch.index.analysis.IkAnalyzerProvider
當一個analyzer在配置文件中被注冊到一個名字(logical name)下后,在mapping定義或者一些API里就可以用這個名字來引用該analyzer了,比如
"message": { "type": "string", "indexAnalyzer": "ik", "searchAnalyzer": "ik" }
4.配置默認分詞器
如果沒有指定索引和搜索用的analyzer,ES會用默認的analyzer來處理,也就是名字(logical name)為default
, default_index
, default_search
的analyzer。 從名字可以看出來,default
是索引和搜索時用的默認的analyzer,default_index
是索引時用的默認的analyzer, default_search
是查詢時用的默認analyzer。
下面是在elasticsearch.yml中配置默認analyzer的例子
index:
analysis:
analyzer:
default_index:
tokenizer: standard
filter: [standard, lowercase, my_synonym, my_snow]
default_search:
tokenizer: standard
filter: [standard, lowercase, stop]
或者用這種格式
index.analysis.analyzer.default.type : "mmseg"
一個analyzer可以起若干別名,比如在下面的例子中,standard analyzer可以用alias1或者alias2來引用
index :
analysis :
analyzer。 :
standard :
alias: [alias1, alias2]
type : standard
stopwords : [test1, test2, test3]
下面是內置的一些analyzer:
analyzer | logical name | description |
---|---|---|
standard analyzer | standard | standard tokenizer, standard filter, lower case filter, stop filter |
simple analyzer | simple | lower case tokenizer |
stop analyzer | stop | lower case tokenizer, stop filter |
keyword analyzer | keyword | 不分詞,內容整體作為一個token(not_analyzed) |
pattern analyzer | whitespace | 正則表達式分詞,默認匹配\W+ |
language analyzers | lang | 各種語言 |
snowball analyzer | snowball | standard tokenizer, standard filter, lower case filter, stop filter, snowball filter |
custom analyzer | custom | 一個Tokenizer, 零個或多個Token Filter, 零個或多個Char Filter |
5.tokenizer
ES內置的tokenizer列表。
tokenizer | logical name | description |
---|---|---|
standard tokenizer | standard | |
edge ngram tokenizer | edgeNGram | |
keyword tokenizer | keyword | 不分詞 |
letter analyzer | letter | 按單詞分 |
lowercase analyzer | lowercase | letter tokenizer, lower case filter |
ngram analyzers | nGram | |
whitespace analyzer | whitespace | 以空格為分隔符拆分 |
pattern analyzer | pattern | 定義分隔符的正則表達式 |
uax email url analyzer | uax_url_email | 不拆分url和email |
path hierarchy analyzer | path_hierarchy | 處理類似/path/to/somthing 樣式的字符串 |
6.token filter
ES內置的token filter列表。
token filter | logical name | description |
---|---|---|
standard filter | standard | |
ascii folding filter | asciifolding | |
length filter | length | 去掉太長或者太短的 |
lowercase filter | lowercase | 轉成小寫 |
ngram filter | nGram | |
edge ngram filter | edgeNGram | |
porter stem filter | porterStem | 波特詞干算法 |
shingle filter | shingle | 定義分隔符的正則表達式 |
stop filter | stop | 移除 stop words |
word delimiter filter | word_delimiter | 將一個單詞再拆成子分詞 |
stemmer token filter | stemmer | |
stemmer override filter | stemmer_override | |
keyword marker filter | keyword_marker | |
keyword repeat filter | keyword_repeat | |
kstem filter | kstem | |
snowball filter | snowball | |
phonetic filter | phonetic | 插件 |
synonym filter | synonyms | 處理同義詞 |
compound word filter | dictionary_decompounder, hyphenation_decompounder | 分解復合詞 |
reverse filter | reverse | 反轉字符串 |
elision filter | elision | 去掉縮略語 |
truncate filter | truncate | 截斷字符串 |
unique filter | unique | |
pattern capture filter | pattern_capture | |
pattern replace filte | pattern_replace | 用正則表達式替換 |
trim filter | trim | 去掉空格 |
limit token count filter | limit | 限制token數量 |
hunspell filter | hunspell | 拼寫檢查 |
common grams filter | common_grams | |
normalization filter | arabic_normalization, persian_normalization |
7.character filter
ES內置的character filter列表
character filter | logical name | description |
---|---|---|
mapping char filter | mapping | 根據配置的映射關系替換字符 |
html strip char filter | html_strip | 去掉HTML元素 |
pattern replace char filter | pattern_replace | 用正則表達式處理字符串 |