接上文 我们发现要实现多条件查询 只能依靠boolQuery
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
@Resource
private HotelMapper hotelMapper;
@Resource
private RestHighLevelClient client;
@Override
public PageResult search(RequestParams params) throws IOException {
//准备Request
SearchRequest request = new SearchRequest("hotel");//操作的数组
//构建boolQuery组合条件
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//boolQuery才是搜索条件 其他查询只是boolQuery中的一部分
request.source().query(boolQuery);
String key = params.getKey();
if (key!=null&&key!="") {
//match查询,会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到。
boolQuery.must(QueryBuilders.matchQuery("all", key));
}else {
//must 中的语句是必须满足的,会影响最终文档的得分
//filter 中的语句是必须满足的,但是不会影响最终的得分
//must_not 中的语句是必须不满足的, 不影响最终的得分
//should中的语句是可以满足的,影响得分,minimum_should_match就是为这兄弟设置的
boolQuery.must(QueryBuilders.matchAllQuery());
}
//城市条件(精确匹配QueryBuilders.termQuery)
if (params.getCity()!=null&&!"".equals(params.getCity())){
//termQuery输入的查询内容是什么,就会按照什么去查询,并不会解析查询内容,对它分词。
boolQuery.filter(QueryBuilders.termQuery("city",params.getCity()));
}//品牌条件(精确匹配QueryBuilders.termQuery)
if (params.getBrand()!=null&&!"".equals(params.getBrand())){
boolQuery.filter(QueryBuilders.termQuery("brand",params.getBrand()));
}//星级匹配
if (params.getStarName()!=null&&!"".equals(params.getStarName())){
boolQuery.filter(QueryBuilders.termQuery("starName",params.getStarName()));
}
//价格条件 (范围匹配QueryBuilders.rangeQuery)
if (params.getMinPrice()!=null¶ms.getMaxPrice()!=null){
boolQuery.filter(QueryBuilders.rangeQuery("price")
.gte(params.getMaxPrice()).lt(params.getMinPrice()));
//gte大于等于 gt大于 lte小于等于 lt小于
}
//分页内容
int page = params.getPage();
int size = params.getSize();
// 偏移量 (page-1)*size
request.source().from((page-1)*size).size(size);
//发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
return getPageResult(search);
}
//对结果进行处理
private PageResult getPageResult(SearchResponse search) {
SearchHits searchHits = search.getHits();
PageResult pageResult = new PageResult();
pageResult.setTotal(searchHits.getTotalHits().value);
SearchHit[] hits = searchHits.getHits();
ArrayList<HotelDoc> list = new ArrayList<>();
for (SearchHit hit : hits) {
// 获取文档source
String json = hit.getSourceAsString();
// 反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
// 放入集合
list.add(hotelDoc);
}
pageResult.setHotels(list);
// 4.4.封装返回
return pageResult;
}
}
要实现多条件查询boolQuery才是搜索条件 其他查询只是boolQuery中的一部分通过判断前端是否传递该数据来实现多条件查询
关于细节我已经写在代码中,条件查询可以抽取成一个方法不会显得代码太臃肿
关于all字段用于拷贝 如果查询多个字段会消耗大量性能 所以拷贝成一个字段all可以提升性能
关于得分 下一章再说
补充:
精确匹配:(用在不能分词的字段keyword等)
精确,指的是查询关键字(或者关键字分词后),必须与目标分词结果完全匹配。
模糊匹配:(用在可以分词的字段text等)
模糊,是指查询关键字与目标关键字可以模糊匹配。
扩展:范围匹配的api
//闭区间查询
QueryBuilder qb1 = QueryBuilders.rangeQuery("${fieldName}").from(${fieldValue1}).to(${fieldValue2});
//开区间查询
QueryBuilder qb1 = QueryBuilders.rangeQuery("${fieldName}").from(${fieldValue1}, false).to(${fieldValue2}, false);
//大于
QueryBuilder qb1 = QueryBuilders.rangeQuery("${fieldName}").gt(${fieldValue});
//大于等于
QueryBuilder qb1 = QueryBuilders.rangeQuery("${fieldName}").gte(${fieldValue});
//小于
QueryBuilder qb1 = QueryBuilders.rangeQuery("${fieldName}").lt(${fieldValue});
//小于等于
QueryBuilder qb1 = QueryBuilders.rangeQuery("${fieldName}").lte(${fieldValue});