?引言
本文參考黑馬 分布式Elastic search
Elasticsearch是一款非常強大的開源搜索引擎,具備非常多強大功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內容
一、我附近的酒店
?需求分析
在酒店列表頁的右側,有一個小地圖,點擊地圖的定位按鈕,地圖會找到你所在的位置:
點擊定位后,會發(fā)送給服務端以下請求json
我們要做的事情就是基于這個location坐標,然后按照距離對周圍酒店排序。實現(xiàn)思路如下:
- 修改RequestParams參數(shù),接收location字段
- 修改search方法業(yè)務邏輯,如果location有值,添加根據(jù)geo_distance排序的功能
?源碼編寫
修改實體類
import lombok.Data;
@Data
public class RequestParams {
private String key;
private Integer page;
private Integer size;
private String sortBy;
private String city;
private String brand;
private String starName;
private Integer minPrice;
private Integer maxPrice;
// 我當前的地理坐標
private String location;
}
距離排序
我們以前學習過排序功能,包括兩種:
- 普通字段排序
- 地理坐標排序
地理坐標 DSL 語法如下
GET /indexName/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"price": "asc"
},
{
"_geo_distance" : {
"FIELD" : "緯度,經(jīng)度",
"order" : "asc",
"unit" : "km"
}
}
]
}
添加距離排序
@Override
public PageResult search(RequestParams params) {
try {
// 1.準備Request
SearchRequest request = new SearchRequest("hotel");
// 2.準備DSL
// 2.1.query
buildBasicQuery(params, request);
// 2.2.分頁
int page = params.getPage();
int size = params.getSize();
request.source().from((page - 1) * size).size(size);
// 2.3.排序
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.發(fā)送請求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.解析響應
return handleResponse(response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
排序距離展示
重啟進行測試:
的卻可以實現(xiàn) 我附近的酒店距離排序,但是沒有展示距離我們有多遠,這個我們應該怎么實現(xiàn)呢?
排序完成后,頁面還要獲取我附近每個酒店的具體距離值,這個值在響應結果中是獨立的:
因此,我們在結果解析階段,除了解析source部分以外,還要得到sort部分,也就是排序的距離,然后放到響應結果中。
我們要做兩件事:
- 修改HotelDoc,添加排序距離字段,用于頁面顯示
- 修改HotelService類中的handleResponse方法,添加對sort值的獲取
添加距離排序字段
import lombok.Data;
import lombok.NoArgsConstructor;
@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();
}
}
修改 handleResponse 方法
重啟進行測試
已成功展示距離。
二、酒店競價排名
需求:讓指定的酒店在搜索結果中排名置頂
?需求分析
要讓指定酒店在搜索結果中排名置頂,效果如圖:
頁面會給指定的酒店添加廣告標記。
那怎樣才能讓指定的酒店排名置頂呢?
我們之前學習過的function_score查詢可以影響算分,算分高了,自然排名也就高了。而function_score包含3個要素:
- 過濾條件:哪些文檔要加分
- 算分函數(shù):如何計算function score
- 加權方式:function score 與 query score如何運算
這里的需求是:讓指定酒店排名靠前。因此我們需要給這些酒店添加一個標記,這樣在過濾條件中就可以根據(jù)這個標記來判斷,是否要提高算分。
比如,我們給酒店添加一個字段:isAD,Boolean類型:
- true:是廣告
- false:不是廣告
這樣function_score包含3個要素就很好確定了:
- 過濾條件:判斷isAD 是否為true
- 算分函數(shù):我們可以用最簡單暴力的weight,固定加權值
- 加權方式:可以用默認的相乘,大大提高算分
因此,業(yè)務的實現(xiàn)步驟包括:
-
給HotelDoc類添加isAD字段,Boolean類型
-
挑選幾個你喜歡的酒店,給它的文檔數(shù)據(jù)添加isAD字段,值為true
-
修改search方法,添加function score功能,給isAD值為true的酒店增加權重
?修改搜索業(yè)務
添加廣告標記
修改實體類
import lombok.Data;
import lombok.NoArgsConstructor;
@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;
// 加入廣告標識
private Boolean isAD;
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();
}
}
隨便設置幾個作為廣告置項
POST /hotel/_update/2056105938
{
"doc": {
"isAD": true
}
}
POST /hotel/_update/38609
{
"doc": {
"isAD": true
}
}
添加算分函數(shù)查詢
接下來我們就要修改查詢條件了。之前是用的boolean 查詢,現(xiàn)在要改成function_socre查詢。
function_score查詢結構如下:
對應的JavaAPI如下:
我們可以將之前寫的boolean查詢作為原始查詢條件放到query中,接下來就是添加過濾條件、算分函數(shù)、加權模式了。所以原來的代碼依然可以沿用。
加入算分查詢
private void buildBasicQuery(RequestParams params, SearchRequest request) {
// 1.構建BooleanQuery
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 && !params.getCity().equals("")) {
boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
}
// 品牌條件
if (params.getBrand() != null && !params.getBrand().equals("")) {
boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
}
// 星級條件
if (params.getStarName() != null && !params.getStarName().equals("")) {
boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
}
// 價格
if (params.getMinPrice() != null && params.getMaxPrice() != null) {
boolQuery.filter(QueryBuilders
.rangeQuery("price")
.gte(params.getMinPrice())
.lte(params.getMaxPrice())
);
}
// 2.算分控制
FunctionScoreQueryBuilder functionScoreQuery =
QueryBuilders.functionScoreQuery(
// 原始查詢,相關性算分的查詢
boolQuery,
// function score的數(shù)組
new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
// 其中的一個function score 元素
new FunctionScoreQueryBuilder.FilterFunctionBuilder(
// 過濾條件
QueryBuilders.termQuery("isAD", true),
// 算分函數(shù)
ScoreFunctionBuilders.weightFactorFunction(10)
)
});
request.source().query(functionScoreQuery);
}
效果展示
?效果圖
?小結
以上就是【Bug 終結者】對 Spring Boot 整合 分布式搜索引擎 Elastic Search 實現(xiàn) 搜索、分頁與結果過濾 的簡單介紹,ES搜索引擎無疑是最優(yōu)秀的分布式搜索引擎,使用它,可大大提高項目的靈活、高效性! 技術改變世界!??!
文章來源:http://www.zghlxwxcb.cn/news/detail-464277.html
如果這篇【文章】有幫助到你,希望可以給【Bug 終結者】點個贊??,創(chuàng)作不易,如果有對【后端技術】、【前端領域】感興趣的小可愛,也歡迎關注?????? 【Bug 終結者】??????,我將會給你帶來巨大的【收獲與驚喜】??????!文章來源地址http://www.zghlxwxcb.cn/news/detail-464277.html
到了這里,關于Spring Boot 整合 分布式搜索引擎 Elastic Search 實現(xiàn) 我附近的、酒店競排的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!