问题背景:通过ES查询数据“沙”,期望查询结果为空,实际查询出数据“黄沙”、“河底沙”。原因:ES使用分词查询,非SQL中 “=” 查询。故取消ES默认分词查询。
1. 取消分词
1.1 添加注解
在需要取消默认分词字段上添加注解 @Field(index = FieldIndex.not_analyzed, type = FieldType.String)
package com.xcb.common.service.dto;
import com.xcb.common.entity.XcbDictItem;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldIndex;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@Document(indexName = XcbDictItemDTO.index)
@Data
public class XcbDictItemDTO implements Serializable {
public static final String index = XcbDictItem.collName + "_query";
private String id;
// 上级编码
private String parentId;
// 字典名称
@Field(index = FieldIndex.not_analyzed, type = FieldType.String)
private String name;
// 字典值
private String value;
// 字典描述
private String desc;
// 排序
private int order = 0;
// 是否隐藏 0否 1隐藏
private Integer show;
private List<XcbDictItemDTO> childItems = Collections.emptyList();
private LocalDateTime createTime;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
XcbDictItemDTO itemDTO = (XcbDictItemDTO) o;
return Objects.equals(id, itemDTO.id);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id);
}
}
1.2. 删除Elasticsearch中数据
1.3. 重新启动项目
2. 处理其他方法需使用分词查询问题
2.1 修改查询语句
WildCardQueryAppender.newInstance(qb).append("name", request.getName());
@Override
public Page<XcbDictItemDTO> getByParentCode(DictItemRequest request, Pageable pageable) {
// 如果没有传sort,默认创建时间降序排列
pageable = SortUtil.getDefaultSortForArticle(pageable);
BoolQueryBuilder qb = QueryBuilders.boolQuery();
if (StringUtils.isNotBlank(request.getParentCode())) {
Optional.ofNullable(dictSerivice.getByCode(request.getParentCode()))
.map(dict -> qb.must(QueryBuilders.termQuery("parentId", dict.getId())));
}
if (StringUtils.isNotBlank(request.getName())) {
WildCardQueryAppender.newInstance(qb).append("name", request.getName());
}
/** 默认查询条件 */
BoolQueryBuilderImpl.getDefaultBoolQueryBuilder(qb, request);
return qb.hasClauses()
? xcbDictItemSearchRepository.search(qb, pageable)
: xcbDictItemSearchRepository.findAll(pageable);
}
2.2 封装WildCardQueryAppender方法
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
public class WildCardQueryAppender {
private BoolQueryBuilder qb;
public static WildCardQueryAppender newInstance(BoolQueryBuilder qb) {
return new WildCardQueryAppender(qb);
}
private WildCardQueryAppender(BoolQueryBuilder qb) {
this.qb = qb;
}
public WildCardQueryAppender append(String name, String value) {
if (StringUtils.isNotBlank(value)) {
this.qb.must(QueryBuilders.wildcardQuery(name, "*" + value + "*"));
}
return this;
}
public BoolQueryBuilder getResult() {
return this.qb;
}
}