快速入门
返回结果直接把json风格的结果封装为SearchReponse对象返回
public class HotelSearchTest {private RestHighLevelClient client;@Testvoid testMatchAll() throws IOException {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSlrequest.source().query(QueryBuilders.matchAllQuery());//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);System.out.println(response);}//执行前初始化@BeforeEachvoid setUp(){this.client=new RestHighLevelClient(RestClient.builder(HttpHost.create("http://xxx.xxx.xxx.xxx:9200")//HttpHost.create("http://xxx.xxx.xxx.xxx:9200") 集群时添加更多的地址));}//销毁@AfterEachvoid tearDown() throws IOException {this.client.close();}
}
响应结果解析
@Testvoid testMatchAll() throws IOException {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSlrequest.source().query(QueryBuilders.matchAllQuery());//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4.解析响应SearchHits searchHits = response.getHits();//4.1获取总条数long total = searchHits.getTotalHits().value;System.out.println("共搜索到"+total+"条数据");//4.2文档数组SearchHit[] hits = searchHits.getHits();//4.3遍历for (SearchHit hit : hits) {//获取文档sourceString json = hit.getSourceAsString();//反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc="+hotelDoc);}}
默认只返回前10条数据
在.source()中query,排序,分页,高亮等功能
QueryBuildes中准备了所有查询,match,match_all,boolean等
match、term、range、bool查询
全文检索查询
@Testvoid testMatch() throws IOException {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSlrequest.source().query(QueryBuilders.matchQuery("all","如家"));//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4.解析响应SearchHits searchHits = response.getHits();//4.1获取总条数long total = searchHits.getTotalHits().value;System.out.println("共搜索到"+total+"条数据");//4.2文档数组SearchHit[] hits = searchHits.getHits();//4.3遍历for (SearchHit hit : hits) {//获取文档sourceString json = hit.getSourceAsString();//反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc="+hotelDoc);}}
对比match和match_all,不同的地方只有一点点,这里直接抽取4往后的公共部分,使用ctrl+alt+m抽取
public class HotelSearchTest {private RestHighLevelClient client;@Testvoid testMatchAll() throws IOException {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSlrequest.source().query(QueryBuilders.matchAllQuery());//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);handleResponse(response);}@Testvoid testMatch() throws IOException {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSlrequest.source().query(QueryBuilders.matchQuery("all","如家"));//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);handleResponse(response);}private static void handleResponse(SearchResponse response) {//4.解析响应SearchHits searchHits = response.getHits();//4.1获取总条数long total = searchHits.getTotalHits().value;System.out.println("共搜索到"+total+"条数据");//4.2文档数组SearchHit[] hits = searchHits.getHits();//4.3遍历for (SearchHit hit : hits) {//获取文档sourceString json = hit.getSourceAsString();//反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc="+hotelDoc);}}//执行前初始化@BeforeEachvoid setUp(){this.client=new RestHighLevelClient(RestClient.builder(HttpHost.create("http://xxx.xxx.xxx.xxx:9200")//HttpHost.create("http://xxx.xxx.xxx.xxx:9200") 集群时添加更多的地址));}//销毁@AfterEachvoid tearDown() throws IOException {this.client.close();}
}
精确查询
一个boolean查询里面包含了term查询和 range查询
@Testvoid testBool() throws IOException {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSl//2.1准备BooleanQueryBoolQueryBuilder boolQuery = QueryBuilders.boolQuery();//2.2添加termboolQuery.must(QueryBuilders.termQuery("city","上海"));//2.3添加rangeboolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));request.source().query(boolQuery);//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);handleResponse(response);}
排序和分页
@Testvoid testPageAndSort() throws IOException {//前端传来页码,每页大小int page=1,size=5;//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSl//2.1准备queryrequest.source().query(QueryBuilders.matchAllQuery());//2.2排序 sortrequest.source().sort("price", SortOrder.ASC);//2.3分页 from,sizerequest.source().from((page-1)*size).size(5);//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);handleResponse(response);}
高亮
构建
@Testvoid testHighlight() throws IOException {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSl//2.1准备queryrequest.source().query(QueryBuilders.matchQuery("all","如家"));//2.2高亮request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4.解析响应handleResponse(response);}
解析
逐层解析json结果
@Testvoid testHighlight() throws IOException {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSl//2.1准备queryrequest.source().query(QueryBuilders.matchQuery("all","如家"));//2.2高亮request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));//3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4.解析响应handleResponse(response);}private static void handleResponse(SearchResponse response) {//4.解析响应SearchHits searchHits = response.getHits();//4.1获取总条数long total = searchHits.getTotalHits().value;System.out.println("共搜索到"+total+"条数据");//4.2文档数组SearchHit[] hits = searchHits.getHits();//4.3遍历for (SearchHit hit : hits) {//获取文档sourceString json = hit.getSourceAsString();//反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);//获取高亮结果Map<String, HighlightField> highlightFields = hit.getHighlightFields();if(!CollectionUtils.isEmpty(highlightFields)) //判断map是否为空的工具类{//根据名字获取高亮结果HighlightField highlightField = highlightFields.get("name");if(highlightField!=null){//获取高亮值String name = highlightField.getFragments()[0].string();//覆盖非高亮结果hotelDoc.setName(name);}}System.out.println("hotelDoc="+hotelDoc);}}
黑马旅游案例——酒店搜索和分页
定义实体类
用于接收前端传来的参数
@Data
public class RequestParams {private String key;private Integer page;private Integer size;private String sortBy;
}
Controller层中
返回值定义
@Data
public class PageResult {private Long total;private List<HotelDoc> hotels;public PageResult() {}public PageResult(Long total, List<HotelDoc> hotels) {this.total = total;this.hotels = hotels;}
}
在启动类中定义一个Bean
@MapperScan("cn.itcast.hotel.mapper")
@SpringBootApplication
public class HotelDemoApplication {public static void main(String[] args) {SpringApplication.run(HotelDemoApplication.class, args);}@Beanpublic RestHighLevelClient client(){return new RestHighLevelClient(RestClient.builder(HttpHost.create("http://xxx.xxx.xxx.xxx:9200")//HttpHost.create("http://xxx.xxx.xxx.xxx:9200") 集群时添加更多的地址));}
}
@RestController
@RequestMapping("hotel")
public class HotelController {@Autowiredprivate IHotelService hotelService;/*** 搜索和分页* @param requestParams* @return*/@PostMapping("/list")public PageResult search(@RequestBody RequestParams requestParams){return hotelService.search(requestParams);}
}
Service层中
public interface IHotelService extends IService<Hotel> {PageResult search(RequestParams requestParams);
}
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {@Autowiredprivate RestHighLevelClient client;@Overridepublic PageResult search(RequestParams requestParams) {try {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSl//2.1queryString key= requestParams.getKey();if(key==null||"".equals(key)){ //没有查询内容时直接查询全部request.source().query(QueryBuilders.matchAllQuery());}else {request.source().query(QueryBuilders.matchQuery("all", key));}//2.2分页int page=requestParams.getPage();int size=requestParams.getSize();request.source().from((page-1)*size).size(size);//3.发送请求SearchResponse response= client.search(request, RequestOptions.DEFAULT);//4.解析响应handleResponse(response);return null;} catch (IOException e) {throw new RuntimeException(e);}}private PageResult handleResponse(SearchResponse response) {//4.解析响应SearchHits searchHits = response.getHits();//4.1获取总条数long total = searchHits.getTotalHits().value;System.out.println("共搜索到"+total+"条数据");//4.2文档数组SearchHit[] hits = searchHits.getHits();//4.3遍历List<HotelDoc> hotels=new ArrayList<>();for (SearchHit hit : hits) {//获取文档sourceString json = hit.getSourceAsString();//反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);hotels.add(hotelDoc);}return new PageResult(total,hotels);}
}
成功搜索
黑马旅游案例——条件过滤
修改DTO
@Data
public class RequestParams {private String key;private Integer page;private Integer size;private String sortBy;private String brand;private String starName;private String city;private Integer minPrice;private Integer maxPrice;
}
Service层中
修改如下,加了多条件过滤,并抽取出去
@Overridepublic PageResult search(RequestParams requestParams) {try {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSl//2.1querybuildBasicQuery(requestParams, request);//2.2分页int page=requestParams.getPage();int size=requestParams.getSize();request.source().from((page-1)*size).size(size);//3.发送请求SearchResponse response= client.search(request, RequestOptions.DEFAULT);//4.解析响应return handleResponse(response);} catch (IOException e) {throw new RuntimeException(e);}}private static void buildBasicQuery(RequestParams requestParams, SearchRequest request) {//构建BooleanQueryBoolQueryBuilder boolQuery = QueryBuilders.boolQuery();//关键字搜索String key= requestParams.getKey();if(key==null||"".equals(key)){ //没有查询内容时直接查询全部boolQuery.must(QueryBuilders.matchAllQuery());}else {boolQuery.must(QueryBuilders.matchQuery("all", key));}//城市条件if(requestParams.getCity()!=null&&!requestParams.getCity().equals("")){boolQuery.filter(QueryBuilders.termQuery("city", requestParams.getCity()));}//品牌条件if(requestParams.getBrand()!=null&&!requestParams.getBrand().equals("")){boolQuery.filter(QueryBuilders.termQuery("brand", requestParams.getBrand()));}//星级条件if(requestParams.getStarName()!=null&&!requestParams.getStarName().equals("")){boolQuery.filter(QueryBuilders.termQuery("starName", requestParams.getStarName()));}//价格条件if(requestParams.getMinPrice()!=null&& requestParams.getMaxPrice()!=null){boolQuery.filter(QueryBuilders.rangeQuery("price").gte(requestParams.getMinPrice()).lte(requestParams.getMaxPrice()));}request.source().query(boolQuery);}
黑马旅游案例——我附近的酒店
距离排序
DTO修改
@Data
public class RequestParams {private String key;private Integer page;private Integer size;private String sortBy;private String brand;private String starName;private String city;private Integer minPrice;private Integer maxPrice;private String location;
}
Service中
修改如下
新增2.3部分
@Overridepublic PageResult search(RequestParams requestParams) {try {//1.准备requestSearchRequest request = new SearchRequest("hotel");//2.准备DSl//2.1querybuildBasicQuery(requestParams, request);//2.2分页int page=requestParams.getPage();int size=requestParams.getSize();request.source().from((page-1)*size).size(size);//2.3排序String location = requestParams.getLocation();if(location!=null&&!location.equals("")){request.source().sort(SortBuilders.geoDistanceSort("location",new GeoPoint(location)).order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));}//3.发送请求SearchResponse response= client.search(request, RequestOptions.DEFAULT);//4.解析响应return handleResponse(response);} catch (IOException e) {throw new RuntimeException(e);}}
DTO修改
@Data
@NoArgsConstructor
public class HotelDoc {private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String location;private String pic;private Object distance;public HotelDoc(Hotel hotel) {this.id = hotel.getId();this.name = hotel.getName();this.address = hotel.getAddress();this.price = hotel.getPrice();this.score = hotel.getScore();this.brand = hotel.getBrand();this.city = hotel.getCity();this.starName = hotel.getStarName();this.business = hotel.getBusiness();this.location = hotel.getLatitude() + ", " + hotel.getLongitude();this.pic = hotel.getPic();}
}
Service修改
private PageResult handleResponse(SearchResponse response) {//4.解析响应SearchHits searchHits = response.getHits();//4.1获取总条数long total = searchHits.getTotalHits().value;System.out.println("共搜索到"+total+"条数据");//4.2文档数组SearchHit[] hits = searchHits.getHits();//4.3遍历List<HotelDoc> hotels=new ArrayList<>();for (SearchHit hit : hits) {//获取文档sourceString json = hit.getSourceAsString();//反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);//获取排序值Object[] sortValues = hit.getSortValues();if(sortValues.length>0){Object sortValue = sortValues[0];hotelDoc.setDistance(sortValue);}hotels.add(hotelDoc);}return new PageResult(total,hotels);}
这里应该成功显示距离附近酒店以及距离了,但是我的电脑获取不到位置。
黑马旅游案例——广告置顶
DTO修改
在HotelDoc中添加一个新字段
private Boolean isAD;
ES数据修改
Service层修改
private static void buildBasicQuery(RequestParams requestParams, SearchRequest request) {//1.构建BooleanQueryBoolQueryBuilder boolQuery = QueryBuilders.boolQuery();//关键字搜索String key= requestParams.getKey();if(key==null||"".equals(key)){ //没有查询内容时直接查询全部boolQuery.must(QueryBuilders.matchAllQuery());}else {boolQuery.must(QueryBuilders.matchQuery("all", key));}//城市条件if(requestParams.getCity()!=null&&!requestParams.getCity().equals("")){boolQuery.filter(QueryBuilders.termQuery("city", requestParams.getCity()));}//品牌条件if(requestParams.getBrand()!=null&&!requestParams.getBrand().equals("")){boolQuery.filter(QueryBuilders.termQuery("brand", requestParams.getBrand()));}//星级条件if(requestParams.getStarName()!=null&&!requestParams.getStarName().equals("")){boolQuery.filter(QueryBuilders.termQuery("starName", requestParams.getStarName()));}//价格条件if(requestParams.getMinPrice()!=null&& requestParams.getMaxPrice()!=null){boolQuery.filter(QueryBuilders.rangeQuery("price").gte(requestParams.getMinPrice()).lte(requestParams.getMaxPrice()));}//2.算分控制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);}
最终查询时就可以看见置顶的广告了