在 Elasticsearch 中處理字符串類型的數據時,如果我們想把整個字符串作為一個完整的 term 存儲汽抚,我們通常會將其類型 type
設定為 keyword
抓狭。但有時這種設定又會給我們帶來麻煩,比如同一個數據再寫入時由于沒有做好清洗造烁,導致大小寫不一致否过,比如 apple
、Apple
兩個實際都是 apple
膨蛮,但當我們去搜索 apple
時卻無法返回 Apple
的文檔叠纹。要解決這個問題,就需要 Normalizer
出場了敞葛。廢話不多說誉察,直接上手看!
1. 上手
我們先來重現一下開篇的問題
PUT test_normalizer
{
"mappings": {
"doc":{
"properties": {
"type":{
"type":"keyword"
}
}
}
}
}
PUT test_normalizer/doc/1
{
"type":"apple"
}
PUT test_normalizer/doc/2
{
"type":"Apple"
}
# 查詢一
GET test_normalizer/_search
{
"query": {
"match":{
"type":"apple"
}
}
}
# 查詢二
GET test_normalizer/_search
{
"query": {
"match":{
"type":"aPple"
}
}
}
大家執(zhí)行后會發(fā)現查詢一
返回了文檔1惹谐,而查詢二
沒有文檔返回持偏,原因如下圖所示:
-
Docs
寫入Elasticsearch
時由于type
是keyword
,分詞結果為原始字符串 - 查詢 Query 時分詞默認是采用和字段寫時相同的配置,因此這里也是
keyword
氨肌,因此分詞結果也是原始字符 - 兩邊的分詞進行匹對鸿秆,便得出了我們上面的結果
2. Normalizer
normalizer
是 keyword
的一個屬性,可以對 keyword
生成的單一 Term
再做進一步的處理怎囚,比如 lowercase
卿叽,即做小寫變換。使用方法和自定義分詞器有些類似恳守,需要自定義考婴,如下所示:
DELETE test_normalizer
# 自定義 normalizer
PUT test_normalizer
{
"settings": {
"analysis": {
"normalizer": {
"lowercase": {
"type": "custom",
"filter": [
"lowercase"
]
}
}
}
},
"mappings": {
"doc": {
"properties": {
"type": {
"type": "keyword"
},
"type_normalizer": {
"type": "keyword",
"normalizer": "lowercase"
}
}
}
}
}
PUT test_normalizer/doc/1
{
"type": "apple",
"type_normalizer": "apple"
}
PUT test_normalizer/doc/2
{
"type": "Apple",
"type_normalizer": "Apple"
}
# 查詢三
GET test_normalizer/_search
{
"query": {
"term":{
"type":"aPple"
}
}
}
# 查詢四
GET test_normalizer/_search
{
"query": {
"term":{
"type_normalizer":"aPple"
}
}
}
我們第一步是自定義了名為 lowercase
的 normalizer,其中filter
類似自定義分詞器中的 filter
催烘,但是可用的種類很少沥阱,詳情大家可以查看官方文檔。然后通過 normalizer
屬性設定到字段type_normalizer
中伊群,然后插入相同的2條文檔考杉。執(zhí)行發(fā)現策精,查詢三
無結果返回,查詢四
返回2條文檔崇棠。
問題解決了咽袜!我們來看下是如何解決的
- 文檔寫入時由于加入了
normalizer
,所有的term
都會被做小寫處理 - 查詢時搜索詞同樣采用有
normalizer
的配置,因此處理后的term
也是小寫的 - 兩邊分詞匹對易茬,就得到了我們上面的結果
3. 總結
本文通過一個實例來給大家講解了 Normalizer
的實際使用場景酬蹋,希望對大家有所幫助及老!