Elasticsearch高手进阶篇(76)
elasticsearch高手进阶_基于completion suggest实现搜索提示
suggest,completion suggest,自动完成,搜索推荐,搜索提示 --> 自动完成,auto completion
auto completion
比如说我们在百度,搜索,你现在搜索“大话西游” --> 百度,自动给你提示,“大话西游电影”,“大话西游小说”, “大话西游手游”
不用你把所有你想要输入的文本都输入完,搜索引擎会自动提示你可能是你想要搜索的那个文本
- 设置mapping
PUT /news_website
{
"mappings": {
"news" : {
"properties" : {
"title" : {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"suggest" : {
"type" : "completion",
"analyzer": "ik_max_word"
}
}
},
"content": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
}
completion,es实现的时候,是非常高性能的,会构建不是倒排索引,也不是正拍索引,就是纯的用于进行前缀搜索的一种特殊的数据结构,而且会全部放在内存中,所以auto completion进行的前缀搜索提示,性能是非常高的
大话西游
- 插入数据
PUT /news_website/news/1
{
"title": "大话西游电影",
"content": "大话西游的电影时隔20年即将在2017年4月重映"
}
PUT /news_website/news/2
{
"title": "大话西游小说",
"content": "某知名网络小说作家已经完成了大话西游同名小说的出版"
}
PUT /news_website/news/3
{
"title": "大话西游手游",
"content": "网易游戏近日出品了大话西游经典IP的手游,正在火爆内测中"
}
- 获取数据
GET /news_website/news/_search
{
"suggest": {
"my-suggest" : {
"prefix" : "大话西游",
"completion" : {
"field" : "title.suggest"
}
}
}
}
{
"took": 10,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 0,
"max_score": 0,
"hits": []
},
"suggest": {
"my-suggest": [
{
"text": "大话西游",
"offset": 0,
"length": 4,
"options": [
{
"text": "大话西游小说",
"_index": "news_website",
"_type": "news",
"_id": "2",
"_score": 1,
"_source": {
"title": "大话西游小说",
"content": "某知名网络小说作家已经完成了大话西游同名小说的出版"
}
},
{
"text": "大话西游手游",
"_index": "news_website",
"_type": "news",
"_id": "3",
"_score": 1,
"_source": {
"title": "大话西游手游",
"content": "网易游戏近日出品了大话西游经典IP的手游,正在火爆内测中"
}
},
{
"text": "大话西游电影",
"_index": "news_website",
"_type": "news",
"_id": "1",
"_score": 1,
"_source": {
"title": "大话西游电影",
"content": "大话西游的电影时隔20年即将在2017年4月重映"
}
}
]
}
]
}
}
- 搜索大话西游电影
GET /news_website/news/_search
{
"query": {
"match": {
"content": "大话西游电影"
}
}
}
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1.3495269,
"hits": [
{
"_index": "news_website",
"_type": "news",
"_id": "1",
"_score": 1.3495269,
"_source": {
"title": "大话西游电影",
"content": "大话西游的电影时隔20年即将在2017年4月重映"
}
},
{
"_index": "news_website",
"_type": "news",
"_id": "3",
"_score": 1.217097,
"_source": {
"title": "大话西游手游",
"content": "网易游戏近日出品了大话西游经典IP的手游,正在火爆内测中"
}
},
{
"_index": "news_website",
"_type": "news",
"_id": "2",
"_score": 1.1299736,
"_source": {
"title": "大话西游小说",
"content": "某知名网络小说作家已经完成了大话西游同名小说的出版"
}
}
]
}
}
Elasticsearch高手进阶篇(77)
elasticsearch高手进阶_使用动态映射模板定制自己的映射策略
dynamic mapping
高级的用法
-
比如说,我们本来没有某个type,或者没有某个field,但是希望在插入数据的时候,es自动为我们做一个识别,动态映射出这个type的mapping,包括每个field的数据类型, 一般用的动态映射,dynamic mapping
-
这里有个问题,如果说,我们其实对dynamic mapping有一些自己独特的需求,比如说,es默认来说,如经过识别到一个数字,field: 10,默认是搞成这个field的数据类型是long,再比如说,如果我们弄了一个field : "10",默认就是text,还会带一个
keyword的内置field。我们没法改变。
但是我们现在就是希望动态映射的时候,根据我们的需求去映射,而不是让es自己按照默认的规则去完成
dyanmic mapping template(动态映射模板)
我们自己预先定义一个模板,然后插入数据的时候,相关的field,如果能够根据我们预先定义的规则,匹配上某个我们预定义的模板,那么就会根据我们的模板来进行mapping,决定这个Field的数据类型
默认的动态映射的效果咋样
DELETE /waws_index
PUT /waws_index/waws_type/1
{
"test_string": "hello world",
"test_number": 10
}
es的自动的默认的,动态映射是咋样的
GET /waws_index/_mapping/waws_type
{
"waws_index": {
"mappings": {
"waws_type": {
"properties": {
"test_number": {
"type": "long"
},
"test_string": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
这个就是es的默认的动态映射规则,可能就不是我们想要的
我们比如说,现在想要的效果是啥?
- test_number,如果是个数字,我们希望默认就是integer类型的
- test_string,如果是字符串,我们希望默认是个text,这个没问题,但是内置的field名字,叫做raw,不叫座keyword,类型还是keyword,保留500个字符
根据类型匹配映射模板
-
动态映射模板,有两种方式
- 第一种:是根据新加入的field的默认的数据类型,来进行匹配,匹配上某个预定义的模板;
- 第二种:是根据新加入的field的名字,去匹配预定义的名字,或者去匹配一个预定义的通配符,然后匹配上某个预定义的模板
-
mapping映射
PUT /waws_index
{
"mappings": {
"waws_type": {
"dynamic_templates": [ # 动态模板
{
"integers": { # 模板的名称
"match_mapping_type": "long", # 匹配的类型(插入的数据的类型)
"mapping": { # 映射成的类型
"type": "integer"
}
}
},
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 500
}
}
}
}
}
]
}
}
}
- 插入数据
PUT /waws_index/waws_type/1
{
"test_long": 1,
"test_string": "hello world"
}
- 获取mapping
GET /waws_index/_mapping/waws_type
{
"waws_index": {
"mappings": {
"waws_type": {
"dynamic_templates": [
{
"integers": {
"match_mapping_type": "long",
"mapping": {
"type": "integer"
}
}
},
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"fields": {
"raw": {
"ignore_above": 500,
"type": "keyword"
}
},
"type": "text"
}
}
}
],
"properties": {
"test_long": {
"type": "integer"
},
"test_string": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 500
}
}
}
}
}
}
}
}
根据字段名配映射模板
- 设置mapping
PUT /waws_index
{
"mappings": {
"waws_type": {
"dynamic_templates": [
{
"string_as_integer": {
"match_mapping_type": "string",
"match": "long_*",
"unmatch": "*_text",
"mapping": {
"type": "integer"
}
}
}
]
}
}
}
举个例子,field : "10",把类似这种field,弄成long型
- 插入一个数据
PUT /waws_index/waws_type/1
{
"test_long": "1",
"test_string": "hello world"
}
- 获取mapping
GET /waws_index/_mapping/waws_type
{
"waws_index": {
"mappings": {
"waws_type": {
"dynamic_templates": [
{
"string_as_integer": {
"match": "long_*",
"unmatch": "*_text",
"match_mapping_type": "string",
"mapping": {
"type": "integer"
}
}
}
],
"properties": {
"test_long": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"test_string": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
场景,有些时候,dynamic mapping + template,每天有一堆日志,每天有一堆数据
这些数据,每天的数据都放一个新的type中,每天的数据都会哗哗的往新的type中写入,此时你就可以定义一个模板,搞一个脚本,每天都预先生成一个新type的模板,里面讲你的各个Field都匹配到一个你预定义的模板中去,就好了