7.2 自动补全

一、拼音分词器

  1. 安装拼音分词器

    1. 地址:https://github.com/medcl/elasticsearch-analysis-pinyin

    2. 解压

    3. 上传(es目录下的plugin文件夹中)

    4. 重启

    5. 测试

二、自定义分词器

  1. 问题

    1. 没有对内容分词

    2. 每个子偶读解析成拼音

    3. 没有汉字

  2. ES中分词器(analyzer)的组成包含三部分:

    1. character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符

    2. tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart

    3. tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等

  3. 自定义分词器:

    1. 创建索引库时,通过settings来配置自定义的analyzer(分词):

      PUT /test
      {
          "settings": {  // 索引库配置
              "analysis": {  // 进行分析
                  "analyzer": {  // 制定分词器
                      "my_analyzer": {  // 制定的分词器名称
                          "tokenizer": "ik_max_word",  // 指定tokenizer,为ik分词器分词
                          "filter": "pinyin"  // 指定filter,转拼音
                      }
                  }
              }
          }
      }

      备注:创建索引库时进行自定义,只对当前索引库有效

    2. 上面的方式设置之后,拼音分词器还会对if分词器分词后的内容进行原规则拆分,因此,对拼音分词器还要进行再次定制

      PUT /test
      {
          "settings": {  // 索引库配置
              "analysis": {  // 进行分析
                  "analyzer": {  // 制定分词器
                      "my_analyzer": {  // 制定的分词器名称
                          "tokenizer": "ik_max_word",  // 指定tokenizer,为ik分词器分词
                          "filter": "py"  // 指定filter,到自己制定的分词器类型
                      }
                  },
                  "filter": {  // 自定义tokenizer filter
                      "py": {  // 自定义过滤器名称
                          "type": "pinyin",  // 过滤器类型,这里是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": ......
      }

      备注:过滤器中,py下面的配置是根据下载地址中给的可配置参数,进行的拼音分词器设置

    3. 定义后的使用方式

      1. 在定义索引库时候,mapping中定义分词器使用自定义分词器

      2. 定义索引库的mapping必须与settings同时存在

    4. 注意:

      1. 拼音分词器适合在穿件倒排索引时候使用,但不能在搜索的时候使用

      2. 解决办法:

        在创建倒排索引库的时候,从制定两个分词器,一个创建时候的分词器,一个查询时候的分词器

        PUT /test
        {
            "settings": {  // 索引库配置
                "analysis": {  // 进行分析
                    "analyzer": {  // 制定分词器
                        "my_analyzer": {  // 制定的分词器名称
                            "tokenizer": "ik_max_word",  // 指定tokenizer,为ik分词器分词
                            "filter": "py"  // 指定filter,到自己制定的分词器类型
                        }
                    },
                    "filter": {  // 自定义tokenizer filter
                        "py": {  // 自定义过滤器名称
                            "type": "pinyin",  // 过滤器类型,这里是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": {
                    "字段名": {
                        "type": "text",
                        "analyzer": "my_analyzer",
                        "search_analyzer": "ik_smart"
                    }
                }
            }
        }

三、自动补全查询

  1. ES提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询的效率,对于文档中字段的类型有一些约束:

    1. 参与补全查询的字段必须是completion类型(创建索引库的时候定义)

    2. 字段的内容一般是用来补全的多个词条形成的数组

  2. 查询语法:

    GET /索引库名称/_search
    {
        "suggest": {
            "title_suggest": {
                "text": "关键字",
                "completion": {
                    "fiels": "补全查询的字段",
                    "skip_duplicates": true,  // 跳过重复的
                    "size": 10  // 获取前10条数据
                }
            }
        }
    }
  3. RestAPI实现自动补全

        @Test
        public void suggestTest() throws IOException {
            // 准备request
            SearchRequest request = new SearchRequest("hotel");
            // 准备DSL
            request.source().suggest(new SuggestBuilder().addSuggestion(
                    "suggestions",  // 自定义的补全查询名称
                    SuggestBuilders.completionSuggestion("suggestion")  // 补全字段
                            .prefix("h")  // 关键字
                            .skipDuplicates(true)  // 不重复
                            .size(10)   // 只取10条
            ));
            // 发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            System.out.println(response);
            // 解析结果
            Suggest suggest = response.getSuggest();
            // 根据名称获取补全结果
            CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
            // 获取列表
            List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
            // 逐条拆分解析
            for (CompletionSuggestion.Entry.Option option : options) {
                String s = option.getText().toString();
                System.out.println(s);
            }
        }

最后更新于

这有帮助吗?