(二)ES常用查询

1、接上一篇介绍索引实体类中相关注解

 正常指定索引类型可根据自己的业务设置  @Field(type=FieldType.Integer),当前涉及中文分词设置 @Field(type=FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
 如果索引字段需要中文分词和拼音分词可以这样设置: @MultiField(mainField = @Field(type=FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word"),
                                          otherFields = @InnerField(type=FieldType.Text,suffix = "pinyin",analyzer = "pinyin"))

2、分词

中文分词目前用的较多的是ik分词插件  注意的点是需要进行分词的字段需要设置type=FieldType.Text,不需要分词的可以指定type = FieldType.Keyword
ik分词器支持最大分词ik_max_word和最小分词ik_smart,这个需要根据自己的业务选择。比如本猿开发的是C端商品搜索,所以选择了最大分词ik_max_word配合全文索引matchQuery使用。

3、分词查询

match query 既能全文检索又能精确查询,配合ik分词后能符合大部分查询。
例如:你需要对商品名称进行分词查询,不在乎分词后的各词根的距离与顺序  只需要全部满足用户输入的所有关键词,那么你可以这样查询:
QueryBuilders.matchQuery("skuTitle",keyWord).operator(Operator.AND)
skuTitle是商品标题,keyWord是用户输入的关键词,Operator.AND表示商品标题要完全匹配用户输入的关键词才能命中索引
Operator.OR 表示商品标题中只要有任一词匹配上就会命中索引  当然这需要结合评分排序  评分越高应该越排在前面。

4、短语查询、前缀查询、普通termQuery查询 模糊查询

 短语查询matchPhrasePrefixQuery  完全匹配,关键词的顺序必须一致
 前缀查询matchBoolPrefixQuery  顾名思义,前缀匹配查询
 termQuery精确查询 完全匹配
 模糊查询wildcardQuery  等价于sql中的like  左模糊和全模糊慎用
 多字段组合查询 multiMatchQuery,例如:
 Map<String,Float> fieldMap = Maps.newHashMap();
 fieldMap.put("skuTitle",10f);
 fieldMap.put("productAlias",10f);
 QueryBuilders.multiMatchQuery(indexReqDTO.getKeyStr(),"skuTitle","virtualTitle","productAlias").operator(Operator.AND).fields(fieldMap);  
 其中的fieldMap 是设置字段的查询权重。

5、模糊查询优化

ES中需要慎用 模糊查询wildcardQuery,特别是全模糊和左模糊,而且还要限制进行模糊查询的关键词长度。
原因是为了加速通配符和正则表达式的匹配速度,Lucene4.0开始会将输入的字符串模式构建成一个DFA (Deterministic Finite Automaton),带有通配符的pattern构造出来的DFA可能会很复杂,开销很大,CPU消耗很高。
所以此处提供两种方案来代替wildcardQuery,一、ES7.9中引入了一种新的wildcard 字段类型,该字段类型经过优化,可在字符串值中快速查找模式,也就是需要升级你的ES版本至7.9及以上。
二、使用nGram分词 + match_phrase查询,nGram是Es自带的默认分词,只需要设置setting,例如:
 final String setting = " {\"analysis\": {\"analyzer\": {\"ngram_analyzer\":{\"tokenizer\":\"ngram_tokenizer\"}},\"tokenizer\": {\"ngram_tokenizer\":{\"type\":\"ngram\",\"min_gram\":1,\"max_gram\":2,\"token_chars\":[\"letter\",\"digit\"]}}}}";
 if(!elasticsearchRestTemplate.indexOps(SuggestWordIndex.class).exists()){
       Document settingDoc = Document.parse(setting);
       IndexOperations indexOps = elasticsearchRestTemplate.indexOps(SuggestWordIndex.class);
       indexOps.create(settingDoc);
       Document document= indexOps.createMapping(SuggestWordIndex.class);
       indexOps.putMapping(document);
 }
elasticsearchRestTemplate.save(suggestWordIndexList);
然后在索引实体类的对应字段上@Field(type = FieldType.Text, analyzer = "ngram_analyzer"),这样使用QueryBuilders.matchPhraseQuery("hitWordNgram",word)就可以实现模糊查询的效果了。

猜你喜欢

转载自blog.csdn.net/rg201612/article/details/125018515
今日推荐