北京网页设计与网站建设,深圳建筑工程公司招聘,wordpress模板编辑,jsp是网站开发语言吗目录 一、自动补全
1.1、效果说明
1.2、安装拼音分词器
1.3、自定义分词器
1.3.1、为什么要自定义分词器
1.3.2、分词器的构成
1.3.3、自定义分词器
1.3.4、面临的问题和解决办法
问题
解决方案
1.4、completion suggester 查询
1.4.1、基本概念和语法
1.4.2、示例…目录 一、自动补全
1.1、效果说明
1.2、安装拼音分词器
1.3、自定义分词器
1.3.1、为什么要自定义分词器
1.3.2、分词器的构成
1.3.3、自定义分词器
1.3.4、面临的问题和解决办法
问题
解决方案
1.4、completion suggester 查询
1.4.1、基本概念和语法
1.4.2、示例
1.4.3、示例黑马旅游
a修改 hotel 索引库结构设置自定义拼音分词器.
b给 HotelDoc 类添加 suggestion 字段
c将数据重新导入到 hotel 索引库中
d基于 JavaRestClient 编写 DSL
1.5、黑马旅游案例
1.5.1、需求
1.5.2、前端对接
1.5.3、实现 controller
1.5.4、创建接口并实现.
1.5.5、效果展示 一、自动补全 1.1、效果说明
当用户在搜索框中输入字符时我们应该提示出与该字符有关的搜索项.
例如百度中输入关键词 byby他的效果如下 1.2、安装拼音分词器 要实现根据字母补全就需要对文档按照拼英分词. 在GitHub 上有一个 es 的拼英分词插件.
地址GitHub - medcl/elasticsearch-analysis-pinyin: This Pinyin Analysis plugin is used to do conversion between Chinese characters and Pinyin.
这里的安装方式和 IK 分词器一样分四步
1. 安装解压. 2. 上传到云服务器中es 的 plugin 目录. 3. 重启 es. 4. 测试. 这里可以看到拼音分词器不光对每个字用拼音进行分词还对每个字的首字母进行分词. 1.3、自定义分词器
1.3.1、为什么要自定义分词器
根据上述测试可以看出.
1. 拼音分词器是将一句话中的每一个字都分成了拼音这没什么实际的用处.
2. 这里并没有分出汉字只有拼英. 实际的使用中用户更多的是使用汉字去搜有拼音只是锦上添花但是也不能只用拼音分词器把汉字丢了.
因此这里我们需要对拼音分词器进行一些自定义的配置. 1.3.2、分词器的构成
想要自定义分词器首先要先了解 es 中分词器的构成.
分词器主要由以下三个部分组成
character filters在 tokenizer 之前对文本的特殊字符进行处理. 比如他会把文本中出现的一些特殊字符转化成汉字例如 :) 开心.tokenizer将文本按照一定的规则切割成词条term. 例如 “我很开心” 会切割成 我、很、开心.tokenizer filter对 tokenizer 进一步处理. 例如将汉字转化成拼音. 1.3.3、自定义分词器
PUT /test
{settings: {analysis: {analyzer: { //自定义分词器my_analyzer: { //自定义分词器名称tokenizer: ik_max_word,filter: py}},filter: {py: { type: pinyin,keep_full_pinyin: false, keep_joined_full_pinyin: true,keep_original: true,limit_first_letter_length: 16,remove_duplicated_term: true,none_chinese_pinyin_tokenize: false}}}}
} “type”: “pinyin”指定使用拼音过滤器进行拼音转换。“keep_full_pinyin”: false表示不保留完整的拼音。如果设置为true则会将完整的拼音保留下来。“keep_joined_full_pinyin”: true表示保留连接的完整拼音。当设置为true时如果某个词的拼音有多个音节那么它们将被连接在一起作为一个完整的拼音。“keep_original”: true表示保留原始词汇。当设置为true时原始的中文词汇也会保留在分词结果中。“limit_first_letter_length”: 16限制拼音首字母的长度。默认为16即只保留拼音首字母的前16个字符。“remove_duplicated_term”: true表示移除重复的拼音词汇。如果设置为true则会移除拼音结果中的重复词汇。“none_chinese_pinyin_tokenize”: false表示是否对非中文文本进行拼音分词处理。当设置为false时非中文文本将保留原样不进行拼音分词处理 例如创建一个 test 索引库来测试自定义分词器.
PUT /test
{settings: {analysis: {analyzer: { my_analyzer: { tokenizer: ik_max_word,filter: py}},filter: {py: { type: pinyin,keep_full_pinyin: false,keep_joined_full_pinyin: true,keep_original: true,limit_first_letter_length: 16,remove_duplicated_term: true,none_chinese_pinyin_tokenize: false}}}},mappings: {properties: {name: {type: text,analyzer: my_analyzer}}}
}
使用此索引库的分词器进行测试 从上图中可以看出
1.不光有拼音还有中文分词.
2.还有中文分词后的英文全拼以及分词首字母. 1.3.4、面临的问题和解决办法
问题
上面实现的拼音分词器还不能应用到实际的生产环境中~
可以想象这样一个场景
如果词库中有这两个词“狮子” 和 “虱子”那么也就意味着创建倒排索引时通过上述自定义的 拼音分词器 就会把这两个词归为一个文档因为他们在分词的时候会分出共同的拼音 shizi 和 sz这就导致他两的文档编号对应同一个词条导致将来用户在搜索框里输入 “狮子” 点击搜索之后会同时搜索出 狮子 和 “虱子” 这并不是我们想看到的. 解决方案
因此字段在创建倒排索引时因该使用 my_analyzer 分词器但是字段在搜索时应该使用 ik_smart 分词器.
也就是说用户输入中文的时候就按中文去搜用户输入拼音的时候才按拼音去搜即使出现上述情况同时搜出这两个词那你是按拼音搜两个都是符合的不存在歧义.
如下
PUT /test
{settings: {analysis: {analyzer: { my_analyzer: { tokenizer: ik_max_word,filter: py}},filter: {py: { type: pinyin,keep_full_pinyin: false,keep_joined_full_pinyin: true,keep_original: true,limit_first_letter_length: 16,remove_duplicated_term: true,none_chinese_pinyin_tokenize: false}}}},mappings: {properties: {name: {type: text,analyzer: my_analyzer //创建倒排索引使用 my_analyzer 分词器.search_analyzer: ik_smart //搜索时使用 ik_smart 分词器.}}}
}
1.4、completion suggester 查询
1.4.1、基本概念和语法
es 中提供了 completion suggester 查询来实现自动补全功能. 这个查询会匹配用户输入内容开头的词条并返回.
为了提高补全查询的效率对于文档中的字段类型有一些约束如下
参与补全查询的字段必须是 completion 类型.参与 自动补全字段 的内容一般是多个词条形成的数组. POST /test2/_search
{suggest: {title_suggest: { //自定义补全名text: s, //用户在搜索框中输入的关键字completion: { // completion 是自动补全中的一种类型(最常用的)field: 补全时需要查询的字段名, //这里的字段名指向的是一个数组字段必须是 completion 类型就是要根据数组中的字段进行查询然后自动补全skip_duplicates: true, //如果查询时有重复的词条是否自动跳过(true 为跳过)size: 10 // 获取前 10 条结果.}}}
}1.4.2、示例
这里我用一个示例来演示 completion suggester 的用法.
首先创建索引库参与自动补全的字段类型必须是 completion.
PUT /test2
{mappings: {properties: {title: {type: completion}}}
}
插入示例数据字段内容一般是用来补全的多个词条形成的数组.
POST test2/_doc
{title: [Sony, WH-1000XM3]
}
POST test2/_doc
{title: [SK-II, PITERA]
}
POST test2/_doc
{title: [Nintendo, switch]
}
这里我们设置关键字为 s来自动补全查询如下
POST /test2/_search
{suggest: {title_suggest: {text: s, completion: {field: title, skip_duplicates: true, size: 10}}}
}1.4.3、示例黑马旅游
这里我们基于之前实现的黑马旅游案例来做栗子实现步骤如下
a修改 hotel 索引库结构设置自定义拼音分词器.
1.设置自定义分词器.
2. 修改索引库的 name、all 字段建立倒排索引使用 拼音分词器搜索时使用 ik 分词器.
3. 给索引库添加一个新字段 suggestion类型为 completion 类型使用自定义分词器.
PUT /hotel
{settings: {analysis: {analyzer: {text_anlyzer: {tokenizer: ik_max_word,filter: py},completion_analyzer: {tokenizer: keyword,filter: py}},filter: {py: {type: pinyin,keep_full_pinyin: false,keep_joined_full_pinyin: true,keep_original: true,limit_first_letter_length: 16,remove_duplicated_term: true,none_chinese_pinyin_tokenize: false}}}},mappings: {properties: {id:{type: keyword},name:{type: text,analyzer: text_anlyzer,search_analyzer: ik_smart,copy_to: all},address:{type: keyword,index: false},price:{type: integer},score:{type: integer},brand:{type: keyword,copy_to: all},city:{type: keyword},starName:{type: keyword},business:{type: keyword,copy_to: all},location:{type: geo_point},pic:{type: keyword,index: false},all:{type: text,analyzer: text_anlyzer,search_analyzer: ik_smart},suggestion:{type: completion,analyzer: completion_analyzer}}}
} b给 HotelDoc 类添加 suggestion 字段
suggestion 字段包含多个字段的数组这里可以使用 List 表示内容包含 brand、business. Psname、all 是可以分词的自动补全的 brand、business 是不可分词的要使用不同的分词器组合. Data
NoArgsConstructor
public class HotelDoc {private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String location;private String pic;private Object distance;private Boolean isAD;private ListString suggestion;public HotelDoc(Hotel hotel) {this.id hotel.getId();this.name hotel.getName();this.address hotel.getAddress();this.price hotel.getPrice();this.score hotel.getScore();this.brand hotel.getBrand();this.city hotel.getCity();this.starName hotel.getStarName();this.business hotel.getBusiness();this.location hotel.getLatitude() , hotel.getLongitude();this.pic hotel.getPic();this.suggestion new ArrayList();suggestion.add(brand);suggestion.add(business);}
}c将数据重新导入到 hotel 索引库中
将 hotel 索引库删了然后重建a 中的 DSL. 通过单元测试将所有信息从数据库同步到 es 上. Testpublic void testBulkDocument() throws IOException {//1.获取酒店所有数据ListHotel hotelList hotelService.list();//2.构造请求BulkRequest request new BulkRequest();//3.准备参数for(Hotel hotel : hotelList) {//转化为文档(主要是地理位置)HotelDoc hotelDoc new HotelDoc(hotel);String json objectMapper.writeValueAsString(hotelDoc);request.add(new IndexRequest(hotel).id(hotel.getId().toString()).source(json, XContentType.JSON));}//4.发送请求client.bulk(request, RequestOptions.DEFAULT);}d基于 JavaRestClient 编写 DSL
例如自动补全关键为 h 的内容. Testpublic void testSuggestion() throws IOException {//1.创建请求SearchRequest request new SearchRequest(hotel);//2.准备参数request.source().suggest(new SuggestBuilder().addSuggestion(testSuggestion,SuggestBuilders.completionSuggestion(suggestion).prefix(h).skipDuplicates(true).size(10)));//3.发送请求接收响应SearchResponse search client.search(request, RequestOptions.DEFAULT);//4.解析响应handlerResponse(search);}这里可以对应着 DSL 语句来写. 对查询结果的处理如下 //4.处理自动补全结果Suggest suggest response.getSuggest();if(suggest ! null) {CompletionSuggestion suggestion suggest.getSuggestion(testSuggestion);for (CompletionSuggestion.Entry.Option option : suggestion.getOptions()) {String text option.getText().toString();System.out.println(text);}}这里可以对应着 DSL 语句来写. 运行结果如下 1.5、黑马旅游案例
1.5.1、需求
首先搜索框的自动补全功能.
最终实现效果就类似于 百度的搜索框比如当我们输入 byby他就会立马自动补全出有关 byby 关键字的信息如下图 1.5.2、前端对接
在搜索框中输入会触发以下请求. 这里前端就传入一个参数 key. 这里约定返回的是一个 List内容就是自动补全的所有信息. 1.5.3、实现 controller
这里使用 RequestParam 接收前端传入的参数然后调用 IhotelService 接口处理即可. RequestMapping(/suggestion)public ListString suggestion(RequestParam(key) String prefix) {return hotelService.suggestion(prefix);}1.5.4、创建接口并实现.
在 IhotelService 接口中创建 suggestion 方法.
public interface IHotelService extends IServiceHotel {PageResult search(RequestParams params);MapString, ListString filters(RequestParams params);ListString suggestion(String prefix);
}接着在 IhotelService 的实现类 HotelService 中实现该方法.
具体的实现就和前面写的测试案例基本一致了~ 要注意的点就是补全的关键字不是写死的而是前端传入的 prefix. Overridepublic ListString suggestion(String prefix) {try {//1.创建请求SearchRequest request new SearchRequest(hotel);//2.准备参数request.source().suggest(new SuggestBuilder().addSuggestion(mySuggestion,SuggestBuilders.completionSuggestion(suggestion).prefix(prefix).skipDuplicates(true).size(10)));//3.发送请求接收响应SearchResponse response client.search(request, RequestOptions.DEFAULT);//4.解析响应(处理自动补全结果)Suggest suggest response.getSuggest();ListString suggestionList new ArrayList();if(suggest ! null) {CompletionSuggestion suggestion suggest.getSuggestion(mySuggestion);for (CompletionSuggestion.Entry.Option option : suggestion.getOptions()) {String text option.getText().toString();suggestionList.add(text);}}return suggestionList;} catch (IOException e) {System.out.println([HotelService] 自动补全失败prefix prefix);e.printStackTrace();return null;}}
}1.5.5、效果展示
输入关键词即可出现自动补全.