最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

[Java]

互联网 admin 41浏览 0评论

[Java]

文章目录

  • 查询建议API
    • 单个建议查询词
    • 多个建议查询词
  • Suggester
    • Term suggester
      • 参数
    • phrase suggester
    • completion suggester
    • 搜索框实现

查询建议(suggest)是为用户提供良好的使用体验。主要包括: 拼写检查; 自动建议查询词(自动补全)。

官方文档:.7/search-suggesters.html#。

查询建议API

查询建议也是使用_search端点地址。在DSL中suggest节点来定义需要的建议查询。

单个建议查询词

POST _search
{"query" : {"match": {"message": "tring out Elasticsearch"}},"suggest" : { <!-- 定义建议查询 -->"my-suggestion" : { <!-- 一个建议查询名 -->"text" : "tring out Elasticsearch", <!-- 查询文本 -->"term" : { <!-- 使用词项建议器 -->"field" : "message" <!-- 指定在哪个字段上获取建议词 -->}}}
}

多个建议查询词

可以多个建议词一起查询:

POST _search
{"suggest": {"my-suggest-1" : {"text" : "tring out Elasticsearch","term" : {"suggest_mode": "missing",      "field" : "message"}},"my-suggest-2" : {"text" : "kmichy","term" : {"field" : "user"}}}
}

也可以多个查询使用同一个查询文本:

POST _search
{"suggest": {"text" : "tring out Elasticsearch","my-suggest-1" : {"term" : {"field" : "message"}},"my-suggest-2" : {"term" : {"field" : "user"}}}
}

Suggester

Suggesters基本的运作原理是将输入的文本分解为token,然后在索引的字典里查找相似的term并返回。 根据使用场景的不同,Elasticsearch里设计了4种类别的Suggester,分别是:

  • Term Suggester
  • Phrase Suggester
  • Completion Suggester
  • Context Suggester

Term suggester

对输入的文本进行分词,为每个词进行模糊匹配查询提供词项建议。对于在索引中存在词默认不提供建议词,不存在的词则根据模糊查询结果进行排序后取一定数量的建议词。

项名说明
text输入文本(用户的输入),根据此文本查找建议
field要查询的字段
analyzer指定分词器
size每个词返回的最大建议词数量
sort建议词的排序方式:
1. score:先按评分排序,再按文档频率、term顺序排;
2. frequency:先按文档频率排序,再按评分、term顺序排
suggest_mode建议模式(控制提供建议词的方式):
1. missing:默认方式,仅在‘要搜索词项’不在索引中存在时,才提供建议词;
2. popular:仅提供频率比‘要搜索词项’高的建议词;
3. always:总是提供建议词;
public void termSuggestSearch(String index, String field, String keyword) {try (RestHighLevelClient rhlClient = ESClient.getClient()) {TermSuggestionBuilder termSuggestion = SuggestBuilders.termSuggestion(field);termSuggestion.text(keyword);termSuggestion.size(5);termSuggestion.suggestMode(TermSuggestionBuilder.SuggestMode.ALWAYS);SuggestBuilder suggestBuilder = new SuggestBuilder();String suggestName = "sugName";suggestBuilder.addSuggestion(suggestName, termSuggestion);SearchRequest searchRequest = new SearchRequest(index);SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.suggest(suggestBuilder);searchRequest.source(sourceBuilder);SearchResponse response = rhlClient.search(searchRequest, RequestOptions.DEFAULT);Suggest suggest = response.getSuggest();if (suggest != null) {Suggest.Suggestion result = suggest.getSuggestion(suggestName);for (Object term : result.getEntries()) {if(term instanceof TermSuggestion.Entry) {TermSuggestion.Entry entry = (TermSuggestion.Entry)term;entry.getOptions().forEach(z->{System.out.println("Text: " + z.getText() + ", freq: " + z.getFreq() + ", score: " + z.getScore());});}else {System.out.println("It is not termSuggestion.Entry: " + term);}}}} catch (Exception ex) {System.out.println(index + " query fail: " + ex);}
}

参数

字段名称说明
max_edits表示被选为建议的edit distance的最大值,只能是1,2之间的数(可以是小数),默认是2
prefix_length表示被选为建议的最小前缀字符的长度,默认为1,增加这个长度可以提高拼写检查的性能,通常拼写错误不会发生在术语的最前面
min_word_length表示推荐文本的最小长度,默认为4
shard_size设置从每个分片检索的建议的最大数量。在reduce阶段,根据size选项只返回前N个建议。默认是和size选项一样
max_inspections表示一个因子,这个参数和shard_size参数相乘以便在分片级别检查更多的候选者的拼写错误,参数默认为5
min_doc_freq表示一个建议中应包含文档数目的最小限制,可以指定为一个确切的数或文档数的相对百分比,默认是0(即不开启此功能)
max_term_freq表示推荐文本可以包含的文档数目的最大限制,可以是一个代表文档频率的确切值,也可以是一个相对百分数(比如0.4),默认是0.01f。这个参数可以用来排除高频术语的拼写检查
string_distance表示一个字符串距离用于和推荐内容相比它们之间的相似性,这个参数可能的值有5个:
internal:表示默认的基于damerau_levenshtein算法,但在比较字符串距离内的索引已经做过高度优化
damerau_levenshtein:是一种基于Damerau-Levenshtein算法的字符串距离算法
levenshtein:是一种基于Levenshtein edit distance算法的字符串距离算法
jaro_winkler:是一种基于Jaro-Winkler算法的字符串距离算法
ngram:是一种基于字符连词的字符串距离算法

phrase suggester

短语建议,在term的基础上,考量多个term间的关系(是否同时出现在索引的原文里,相邻程度,以及词频等):

public void phraseSuggestSearch(String index, String field, String keyword) {try (RestHighLevelClient rhlClient = ESClient.getClient()) {PhraseSuggestionBuilder phraseSuggestion = SuggestBuilders.phraseSuggestion(field);phraseSuggestion.text(keyword);phraseSuggestion.size(5);SuggestBuilder suggestBuilder = new SuggestBuilder();String suggestName = "sugName";suggestBuilder.addSuggestion(suggestName, phraseSuggestion);SearchRequest searchRequest = new SearchRequest(index);SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.suggest(suggestBuilder);searchRequest.source(sourceBuilder);SearchResponse response = rhlClient.search(searchRequest, RequestOptions.DEFAULT);Suggest suggest = response.getSuggest();if (suggest != null) {Suggest.Suggestion result = suggest.getSuggestion(suggestName);for (Object term : result.getEntries()) {if(term instanceof PhraseSuggestion.Entry) {PhraseSuggestion.Entry entry = (PhraseSuggestion.Entry)term;entry.getOptions().forEach(z->{System.out.println("Text: " + z.getText() + ", score: " + z.getScore());});}else {System.out.println("It is not phraseSuggestion.Entry: " + term);}}}} catch (Exception ex) {System.out.println(index + " query fail: " + ex);}
}

completion suggester

Completion Suggester提供自动完成/随类型搜索的功能;这是一种导航特性,可以在用户键入时引导他们找到相关结果,提高搜索精度。因此实现上它和前面两个Suggester采用了不同的数据结构,索引并非通过倒排来完成,而是将analyze过的数据编码成FST和索引一起存放。对于一个open状态的索引,FST会被ES整个装载到内存里的,进行前缀查找速度极快。但是FST只能用于前缀查找,这也是Completion Suggester的局限所在。

为了使用自动补全,索引中用来提供补全建议的字段需特殊设计,字段类型为 completion。

搜索框实现

要实现搜索框的补全/纠错功能:

  • 在用户刚开始输入的过程中,使用Completion Suggester进行关键词前缀匹配,刚开始匹配项会比较多,随着用户输入字符增多,匹配项越来越少。
  • 如果用户输入比较精准,可能Completion Suggester的结果已经够好,用户已经可以看到理想的备选项了。 如果Completion Suggester已经到了零匹配,那么可以猜测是否用户有输入错误,这时候可以尝试一下Phrase Suggester。如果Phrase Suggester没有找到任何option,开始尝试term Suggester。
  • 精准程度上(Precision)看: Completion > Phrase > term, 而召回率上(Recall)则反之。从性能上看,Completion Suggester是最快的,如果能满足业务需求,只用Completion Suggester做前缀匹配是最理想的。Phrase和Term由于是做倒排索引的搜索,相比较而言性能应该要低不少,应尽量控制suggester用到的索引的数据量,最理想的状况是经过一定时间预热后,索引可以全量map到内存。

[Java]

文章目录

  • 查询建议API
    • 单个建议查询词
    • 多个建议查询词
  • Suggester
    • Term suggester
      • 参数
    • phrase suggester
    • completion suggester
    • 搜索框实现

查询建议(suggest)是为用户提供良好的使用体验。主要包括: 拼写检查; 自动建议查询词(自动补全)。

官方文档:.7/search-suggesters.html#。

查询建议API

查询建议也是使用_search端点地址。在DSL中suggest节点来定义需要的建议查询。

单个建议查询词

POST _search
{"query" : {"match": {"message": "tring out Elasticsearch"}},"suggest" : { <!-- 定义建议查询 -->"my-suggestion" : { <!-- 一个建议查询名 -->"text" : "tring out Elasticsearch", <!-- 查询文本 -->"term" : { <!-- 使用词项建议器 -->"field" : "message" <!-- 指定在哪个字段上获取建议词 -->}}}
}

多个建议查询词

可以多个建议词一起查询:

POST _search
{"suggest": {"my-suggest-1" : {"text" : "tring out Elasticsearch","term" : {"suggest_mode": "missing",      "field" : "message"}},"my-suggest-2" : {"text" : "kmichy","term" : {"field" : "user"}}}
}

也可以多个查询使用同一个查询文本:

POST _search
{"suggest": {"text" : "tring out Elasticsearch","my-suggest-1" : {"term" : {"field" : "message"}},"my-suggest-2" : {"term" : {"field" : "user"}}}
}

Suggester

Suggesters基本的运作原理是将输入的文本分解为token,然后在索引的字典里查找相似的term并返回。 根据使用场景的不同,Elasticsearch里设计了4种类别的Suggester,分别是:

  • Term Suggester
  • Phrase Suggester
  • Completion Suggester
  • Context Suggester

Term suggester

对输入的文本进行分词,为每个词进行模糊匹配查询提供词项建议。对于在索引中存在词默认不提供建议词,不存在的词则根据模糊查询结果进行排序后取一定数量的建议词。

项名说明
text输入文本(用户的输入),根据此文本查找建议
field要查询的字段
analyzer指定分词器
size每个词返回的最大建议词数量
sort建议词的排序方式:
1. score:先按评分排序,再按文档频率、term顺序排;
2. frequency:先按文档频率排序,再按评分、term顺序排
suggest_mode建议模式(控制提供建议词的方式):
1. missing:默认方式,仅在‘要搜索词项’不在索引中存在时,才提供建议词;
2. popular:仅提供频率比‘要搜索词项’高的建议词;
3. always:总是提供建议词;
public void termSuggestSearch(String index, String field, String keyword) {try (RestHighLevelClient rhlClient = ESClient.getClient()) {TermSuggestionBuilder termSuggestion = SuggestBuilders.termSuggestion(field);termSuggestion.text(keyword);termSuggestion.size(5);termSuggestion.suggestMode(TermSuggestionBuilder.SuggestMode.ALWAYS);SuggestBuilder suggestBuilder = new SuggestBuilder();String suggestName = "sugName";suggestBuilder.addSuggestion(suggestName, termSuggestion);SearchRequest searchRequest = new SearchRequest(index);SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.suggest(suggestBuilder);searchRequest.source(sourceBuilder);SearchResponse response = rhlClient.search(searchRequest, RequestOptions.DEFAULT);Suggest suggest = response.getSuggest();if (suggest != null) {Suggest.Suggestion result = suggest.getSuggestion(suggestName);for (Object term : result.getEntries()) {if(term instanceof TermSuggestion.Entry) {TermSuggestion.Entry entry = (TermSuggestion.Entry)term;entry.getOptions().forEach(z->{System.out.println("Text: " + z.getText() + ", freq: " + z.getFreq() + ", score: " + z.getScore());});}else {System.out.println("It is not termSuggestion.Entry: " + term);}}}} catch (Exception ex) {System.out.println(index + " query fail: " + ex);}
}

参数

字段名称说明
max_edits表示被选为建议的edit distance的最大值,只能是1,2之间的数(可以是小数),默认是2
prefix_length表示被选为建议的最小前缀字符的长度,默认为1,增加这个长度可以提高拼写检查的性能,通常拼写错误不会发生在术语的最前面
min_word_length表示推荐文本的最小长度,默认为4
shard_size设置从每个分片检索的建议的最大数量。在reduce阶段,根据size选项只返回前N个建议。默认是和size选项一样
max_inspections表示一个因子,这个参数和shard_size参数相乘以便在分片级别检查更多的候选者的拼写错误,参数默认为5
min_doc_freq表示一个建议中应包含文档数目的最小限制,可以指定为一个确切的数或文档数的相对百分比,默认是0(即不开启此功能)
max_term_freq表示推荐文本可以包含的文档数目的最大限制,可以是一个代表文档频率的确切值,也可以是一个相对百分数(比如0.4),默认是0.01f。这个参数可以用来排除高频术语的拼写检查
string_distance表示一个字符串距离用于和推荐内容相比它们之间的相似性,这个参数可能的值有5个:
internal:表示默认的基于damerau_levenshtein算法,但在比较字符串距离内的索引已经做过高度优化
damerau_levenshtein:是一种基于Damerau-Levenshtein算法的字符串距离算法
levenshtein:是一种基于Levenshtein edit distance算法的字符串距离算法
jaro_winkler:是一种基于Jaro-Winkler算法的字符串距离算法
ngram:是一种基于字符连词的字符串距离算法

phrase suggester

短语建议,在term的基础上,考量多个term间的关系(是否同时出现在索引的原文里,相邻程度,以及词频等):

public void phraseSuggestSearch(String index, String field, String keyword) {try (RestHighLevelClient rhlClient = ESClient.getClient()) {PhraseSuggestionBuilder phraseSuggestion = SuggestBuilders.phraseSuggestion(field);phraseSuggestion.text(keyword);phraseSuggestion.size(5);SuggestBuilder suggestBuilder = new SuggestBuilder();String suggestName = "sugName";suggestBuilder.addSuggestion(suggestName, phraseSuggestion);SearchRequest searchRequest = new SearchRequest(index);SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.suggest(suggestBuilder);searchRequest.source(sourceBuilder);SearchResponse response = rhlClient.search(searchRequest, RequestOptions.DEFAULT);Suggest suggest = response.getSuggest();if (suggest != null) {Suggest.Suggestion result = suggest.getSuggestion(suggestName);for (Object term : result.getEntries()) {if(term instanceof PhraseSuggestion.Entry) {PhraseSuggestion.Entry entry = (PhraseSuggestion.Entry)term;entry.getOptions().forEach(z->{System.out.println("Text: " + z.getText() + ", score: " + z.getScore());});}else {System.out.println("It is not phraseSuggestion.Entry: " + term);}}}} catch (Exception ex) {System.out.println(index + " query fail: " + ex);}
}

completion suggester

Completion Suggester提供自动完成/随类型搜索的功能;这是一种导航特性,可以在用户键入时引导他们找到相关结果,提高搜索精度。因此实现上它和前面两个Suggester采用了不同的数据结构,索引并非通过倒排来完成,而是将analyze过的数据编码成FST和索引一起存放。对于一个open状态的索引,FST会被ES整个装载到内存里的,进行前缀查找速度极快。但是FST只能用于前缀查找,这也是Completion Suggester的局限所在。

为了使用自动补全,索引中用来提供补全建议的字段需特殊设计,字段类型为 completion。

搜索框实现

要实现搜索框的补全/纠错功能:

  • 在用户刚开始输入的过程中,使用Completion Suggester进行关键词前缀匹配,刚开始匹配项会比较多,随着用户输入字符增多,匹配项越来越少。
  • 如果用户输入比较精准,可能Completion Suggester的结果已经够好,用户已经可以看到理想的备选项了。 如果Completion Suggester已经到了零匹配,那么可以猜测是否用户有输入错误,这时候可以尝试一下Phrase Suggester。如果Phrase Suggester没有找到任何option,开始尝试term Suggester。
  • 精准程度上(Precision)看: Completion > Phrase > term, 而召回率上(Recall)则反之。从性能上看,Completion Suggester是最快的,如果能满足业务需求,只用Completion Suggester做前缀匹配是最理想的。Phrase和Term由于是做倒排索引的搜索,相比较而言性能应该要低不少,应尽量控制suggester用到的索引的数据量,最理想的状况是经过一定时间预热后,索引可以全量map到内存。
发布评论

评论列表 (0)

  1. 暂无评论