当我们点击搜索时
@Bean
public RestHighLevelClient client(){
return new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")));
}
2、创建实体类
RequesParams类
@Data
public class RequestParams {
private String key;
private Integer page;
private Integer size;
private String sortBy;
}
PageResult类
@Data
public class PageResult {
private Long total;
private List hotels;
public PageResult() {
}
public PageResult(Long total, List hotels) {
this.total = total;
this.hotels = hotels;
}
}
3、自定义一个搜索方法
public interface IHotelService extends IService<Hotel> {
PageResult searchs(RequestParams params);
}
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
@Autowired
private RestHighLevelClient client;
@Override
public PageResult searchs(RequestParams params) {
try {
SearchRequest request = new SearchRequest("hotel");
//准备dsl
//根据关键字搜索和分页
//健壮性判断
String key = params.getKey();
if (key == null || "".equals(key)) {
request.source().query(QueryBuilders.matchAllQuery());
} else {
request.source().query(QueryBuilders.matchQuery("all", key));
}
//分页
//页码
int page = params.getPage();
int size = params.getSize();
request.source().from((page - 1) * size).size(size);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
return extracted(search);
}
catch (IOException e){
throw new RuntimeException(e);
}
}
private PageResult extracted(SearchResponse search) {
//解析结果
SearchHits hits = search.getHits();
//获取总条数
long totalHits = hits.getTotalHits().value;
// System.err.println("共搜索到"+totalHits+"条数据");
List<HotelDoc> hotels=new ArrayList<>();
//文档数组
SearchHit[] hitsList = hits.getHits();
//遍历
for (SearchHit documentFields : hitsList) {
String sourceAsString = documentFields.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
hotels.add(hotelDoc);
}
//封装返回
return new PageResult(totalHits,hotels);
}
}
4、创建HotelController类
@RestController
@RequestMapping("/hotel")
public class HotelControlller {
@Autowired
private IHotelService hotelService;
@PostMapping("/list")
public PageResult search(@RequestBody RequestParams params){
return hotelService.searchs(params);
}
}
1、修改实体类RequestParams
@Data
public class RequestParams {
private String key;
private Integer page;
private Integer size;
private String sortBy;
private String brand;
private String city;
private String starName;
private Integer minPrice;
private Integer maxPrice;
}
2、修改searchs代码
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
@Autowired
private RestHighLevelClient client;
@Override
public PageResult searchs(RequestParams params) {
try {
SearchRequest request = new SearchRequest("hotel");
//准备dsl
//构建BooleanQuery
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
request.source().query(boolQuery);
//根据关键字搜索和分页
//健壮性判断
//分页
//页码
int page = params.getPage();
int size = params.getSize();
request.source().from((page - 1) * size).size(size);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
return extracted(search);
}
catch (IOException e){
throw new RuntimeException(e);
}
}
//拆分成一个函数
private static void buildBasicQuery(RequestParams params, SearchRequest request) {
BoolQueryBuilder boolQuery=QueryBuilders.boolQuery();
String key = params.getKey();
if (key == null || "".equals(key)) {
boolQuery.must(QueryBuilders.matchAllQuery());
} else {
boolQuery.must(QueryBuilders.matchQuery("all", key));
}
//条件过滤
//城市
if (params.getCity()!=null&&!"".equals(params.getCity())){
boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
}
//品牌
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()));
}
//价格范围
if (params.getMaxPrice()!=null&& params.getMinPrice()!=null){
//价格过滤
boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
}
request.source().query(boolQuery);
}
private PageResult extracted(SearchResponse search) {
//解析结果
SearchHits hits = search.getHits();
//获取总条数
long totalHits = hits.getTotalHits().value;
// System.err.println("共搜索到"+totalHits+"条数据");
List<HotelDoc> hotels=new ArrayList<>();
//文档数组
SearchHit[] hitsList = hits.getHits();
//遍历
for (SearchHit documentFields : hitsList) {
String sourceAsString = documentFields.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
hotels.add(hotelDoc);
}
//封装返回
return new PageResult(totalHits,hotels);
}
}
距离排序
显示具体的距离值
1.在实体类HotelDoc中添加距离属性
private Object distance;
在实体类RequestParams中添加location属性
private String location;
2、编写排序方式
//添加位置排序功能
String location = params.getLocation();
if (location!=null&&!location.equals("")){
request.source().sort(SortBuilders.geoDistanceSort("location",new GeoPoint(location))
.order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));
}
3、修改处理结果
//获取距离
Object[] sortValues = documentFields.getSortValues();
if (sortValues.length>0){
Object sortValue=sortValues[0];
hotelDoc.setDistance(sortValue);
}
我们需要给置顶的酒店添加一个标记,然后来利用function score给带有指定的文档增加权重
1、在实体类HtmllDoc中
private Boolean isAD;
2、修改设置置顶
POST /hotel/_update/1975922994
{
"doc": {
"isAD":true
}
}
3、修改排序逻辑
private static void buildBasicQuery(RequestParams params, SearchRequest request) {
BoolQueryBuilder boolQuery=QueryBuilders.boolQuery();
String key = params.getKey();
if (key == null || "".equals(key)) {
boolQuery.must(QueryBuilders.matchAllQuery());
} else {
boolQuery.must(QueryBuilders.matchQuery("all", key));
}
//条件过滤
//城市
if (params.getCity()!=null&&!"".equals(params.getCity())){
boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
}
//品牌
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()));
}
//价格范围
if (params.getMaxPrice()!=null&& params.getMinPrice()!=null){
//价格过滤
boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
}
//算分控制
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(
//原始查询
boolQuery,
//function score数组
new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
//具体的一个function score数组
new FunctionScoreQueryBuilder.FilterFunctionBuilder(
//满足条件参与算分
QueryBuilders.termQuery("isAD",true),
ScoreFunctionBuilders.weightFactorFunction(10)
)
});
request.source().query(functionScoreQueryBuilder);
}