相信大家都知道 搜索引擎除了能夠返回你想要的內容外,還有另外一個重要的功能,就是搜索框的字段補全,當用戶在輸入框輸入一段文本的前幾個詞時,下面會出現很多相關的候選詞提示,那么在es7.0中這個場景很容易就通過 search_as_you_type 來實現
1、介紹
search_as_you_type filed是elasticsearch 7.0 新增的數據類型,它為用戶提供了一種開箱即用的搜索即可見的解決方案,內部會自動拆分為多個子字段索引以支持高效查詢,目前 search_as_you_type 實現前綴,中綴查詢。
2、操作
- mapping
PUT my_index
{
"mappings": {
"properties": {
"my_field": {
"type": "search_as_you_type"
}
}
}
}
上述操作會自動創建如下幾個field:
字段 | 分詞器 |
---|---|
my_field | 使用mapping時指定的分詞器,沒指定將使用默認分詞器 |
my_field._2gram | 使用2元gram進行分詞 |
my_field._3gram | 使用3元gram進行分詞 |
my_field._index_prefix | 使用edge gram進行分詞操作,相當于1元gram(類似sql中的 like ‘abc%’) |
N-gram中的N可以通過mapping中增加 max_shingle_size 參數進行控制,存放整型數據,默認值是3,可接受范圍是[2,4],其中._index_prefix 會一直存在。
增大 max_shingle_size 會帶來更多的索引存儲,檢索性能也會受到影響,一般情況下默認值就夠用了。
索引到root field的文本也會被索引到其它的子字段里:
PUT my_index/_doc/1?refresh
{
"my_field": "quick brown fox jump lazy dog"
}
實現 search_as_you_type 最高效的查詢時使用類型為bool_prefix的multi_match query,下面是一個例子:
GET my_index/_search
{
"query": {
"multi_match": {
"query": "brown f",
"type": "bool_prefix",
"fields": [
"my_field",
"my_field._2gram",
"my_field._3gram"
]
}
}
}
{
"took" : 44,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.8630463,
"hits" : [
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.8630463,
"_source" : {
"my_field" : "quick brown fox jump lazy dog"
}
}
]
}
}
雖然 match_phrase_prefix 也可以實現上述需求,但考慮到性能問題建議不要這么做。
-
參數
如果沒做特別說明,search_as_you_type 類型的mapping參數與普通 text 類型的mapping參數是一致的:
參數 | 說明 |
---|---|
analyzer | 指定索引期間和搜索期間的分詞器(索引期間的分詞器能使用 search_analyzer參數覆蓋),默認的分詞器是 standard |
index | 是否進行索引 true 或 false ,設置為false將不能被檢索 |
index_options | 文本索引的粒度,支持 docs、freqs、positions、offsets |
norms | true 或 false;存儲該字段歸一化因子,如果字段不需要參與評分,可設置為false |
store | 是否獨立存儲field數據 |
search_analyzer | 查詢時分詞器 |
search_quote_analyzer | 默認使用 search_analyzer |
similarity | 指定相似度算法,默認是BM25 |
term_vector | 是否存儲term向量,默認是no |
所有在my_field 上的前綴查詢都會被重寫成在 _index_prefix 字段上的查詢,因為_index_prefix 會對每個term的前綴會直接索引,所以比傳統的在text字段上進行prefix查詢高效許多