feat(功能新增): 功能新增

功能新增
This commit is contained in:
Zerroi 2024-04-14 15:24:24 +08:00
parent 39cbd32dad
commit 58669de46a
13 changed files with 357 additions and 55 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.idea
/target
/src/test

View File

@ -15,5 +15,17 @@
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
<data-source source="LOCAL" name="postgres@192.168.249.131" uuid="25040236-e82f-4442-9c6e-5e1688bc5e04">
<driver-ref>postgresql</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
<jdbc-url>jdbc:postgresql://192.168.249.131:5432/postgres</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

15
.idea/git_toolbox_prj.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

View File

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
@ -16,5 +21,10 @@
<option name="name" value="Central Repository" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
<remote-repository>
<option name="id" value="alimaven" />
<option name="name" value="aliyun maven" />
<option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
</remote-repository>
</component>
</project>

View File

@ -1,13 +1,14 @@
package cn.itcast.hotel;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@MapperScan("cn.itcast.hotel.mapper")
@SpringBootApplication
public class HotelDemoApplication {
@ -16,4 +17,11 @@ public class HotelDemoApplication {
SpringApplication.run(HotelDemoApplication.class, args);
}
@Bean
public RestHighLevelClient restHighLevelClient() {
return new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.249.131:9200")
));
}
}

View File

@ -0,0 +1,24 @@
package cn.itcast.hotel.controller;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/hotel")
public class HotelController {
@Resource
private IHotelService hotelService;
@PostMapping("/list")
public PageResult search(@RequestBody RequestParams requestParams) {
return hotelService.search(requestParams);
}
}

View File

@ -17,6 +17,8 @@ public class HotelDoc {
private String business;
private String location;
private String pic;
private Object distance;
private Boolean isAd;
public HotelDoc(Hotel hotel) {
this.id = hotel.getId();

View File

@ -0,0 +1,15 @@
package cn.itcast.hotel.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult {
private Long total;
private List<HotelDoc> hotelList;
}

View File

@ -0,0 +1,17 @@
package cn.itcast.hotel.pojo;
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;
}

View File

@ -1,7 +1,10 @@
package cn.itcast.hotel.service;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import com.baomidou.mybatisplus.extension.service.IService;
public interface IHotelService extends IService<Hotel> {
PageResult search(RequestParams requestParams);
}

View File

@ -2,10 +2,96 @@ package cn.itcast.hotel.service.impl;
import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
@Resource
private RestHighLevelClient client;
@Override
public PageResult search(RequestParams params) {
SearchRequest request = new SearchRequest("hotel");
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
paramCheck(params, boolQuery);
Integer page = params.getPage();
Integer size = params.getSize();
request.source().from((page - 1) * size).size(size);
if (StringUtils.isEmpty(params.getLocation())) {
request.source().sort(SortBuilders
.geoDistanceSort("location", new GeoPoint(params.getLocation()))
.order(SortOrder.ASC)
.unit(DistanceUnit.KILOMETERS)
);
}
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
return handleResponse(response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void paramCheck(RequestParams params, BoolQueryBuilder boolQuery) {
if (StringUtils.isEmpty(params.getKey())) {
boolQuery.must(QueryBuilders.matchAllQuery());
} else {
boolQuery.must(QueryBuilders.matchQuery("all", params.getKey()));
}
if (StringUtils.isEmpty(params.getCity())) {
boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
}
if (StringUtils.isEmpty(params.getStarName())) {
boolQuery.filter(QueryBuilders.termQuery("city", params.getSize()));
}
if (params.getMinPrice() != null && params.getMaxPrice() != null) {
boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
}
}
private PageResult handleResponse(SearchResponse response) throws IOException {
SearchHit[] searchHits = response.getHits().getHits();
long total = response.getHits().getTotalHits().value;
List<HotelDoc> hotelDocList = new ArrayList<>();
for (SearchHit searchHit : searchHits) {
String source = searchHit.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(source, HotelDoc.class);
Object[] sortValues = searchHit.getSortValues();
hotelDoc.setDistance(ObjectUtils.isEmpty(sortValues) ? null : sortValues[0]);
hotelDocList.add(hotelDoc);
}
return new PageResult(total, hotelDocList);
}
}

View File

@ -21,7 +21,9 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
@ -29,84 +31,63 @@ class HotelDocumentTest {
private RestHighLevelClient client;
@Autowired
@Resource
private IHotelService hotelService;
@Test
void testAddDocument() throws IOException {
// 1.查询数据库hotel数据
Hotel hotel = hotelService.getById(61083L);
// 2.转换为HotelDoc
Hotel hotel = hotelService.getById(56227L);
HotelDoc hotelDoc = new HotelDoc(hotel);
// 3.转JSON
String json = JSON.toJSONString(hotelDoc);
// 1.准备Request
IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
// 2.准备请求参数DSL其实就是文档的JSON字符串
request.source(json, XContentType.JSON);
// 3.发送请求
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
// 发送请求
client.index(request, RequestOptions.DEFAULT);
}
@Test
void testGetDocumentById() throws IOException {
// 1.准备Request // GET /hotel/_doc/{id}
GetRequest request = new GetRequest("hotel", "61083");
// 2.发送请求
void testGetDocument() throws IOException {
GetRequest request = new GetRequest("hotel", "56227");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 3.解析响应结果
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println("hotelDoc = " + hotelDoc);
String source = response.getSourceAsString();
HotelDoc hotel = JSON.parseObject(source, HotelDoc.class);
System.out.println("hotel = " + hotel);
}
@Test
void testDeleteDocumentById() throws IOException {
// 1.准备Request // DELETE /hotel/_doc/{id}
DeleteRequest request = new DeleteRequest("hotel", "61083");
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
}
@Test
void testUpdateById() throws IOException {
// 1.准备Request
UpdateRequest request = new UpdateRequest("hotel", "61083");
// 2.准备参数
request.doc(
"price", "870"
void testUpdateDocument() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("hotel", "56227");
updateRequest.doc(
"price", "999",
"starName", "四钻"
);
// 3.发送请求
client.update(request, RequestOptions.DEFAULT);
client.update(updateRequest, RequestOptions.DEFAULT);
}
@Test
void testBulkRequest() throws IOException {
// 查询所有的酒店数据
List<Hotel> list = hotelService.list();
void testDeleteDocument() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("hotel", "56227");
client.delete(deleteRequest, RequestOptions.DEFAULT);
}
// 1.准备Request
BulkRequest request = new BulkRequest();
// 2.准备参数
for (Hotel hotel : list) {
// 2.1.转为HotelDoc
@Test
void testBulkDocument() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
List<Hotel> hotelList = hotelService.list();
for (Hotel hotel : hotelList) {
HotelDoc hotelDoc = new HotelDoc(hotel);
// 2.2.转json
String json = JSON.toJSONString(hotelDoc);
// 2.3.添加请求
request.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(json, XContentType.JSON));
bulkRequest.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc), XContentType.JSON));
}
client.bulk(bulkRequest, RequestOptions.DEFAULT);
// 3.发送请求
client.bulk(request, RequestOptions.DEFAULT);
}
@BeforeEach
void setUp() {
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.150.101:9200")
HttpHost.create("http://192.168.249.131:9200")
));
}

View File

@ -0,0 +1,126 @@
package cn.itcast.hotel;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.util.Map;
@SpringBootTest
public class HotelQueryTest {
private RestHighLevelClient client;
@Test
void testMatchAll() throws IOException {
// 准备Request
SearchRequest request = new SearchRequest("hotel");
// 准备DSL
request.source().query(QueryBuilders.matchAllQuery());
// 发送请求
handleResponse(request);
}
@Test
void testMatch() throws IOException {
// 准备Request
SearchRequest request = new SearchRequest("hotel");
// 准备DSL
request.source().query(QueryBuilders.matchQuery("all", "如家"));
handleResponse(request);
}
@Test
void testTerm() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.termQuery("city", "成都"));
handleResponse(request);
}
@Test
void testBoolean() throws IOException {
SearchRequest request = new SearchRequest("hotel");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must().add(QueryBuilders.termQuery("city", "上海"));
boolQueryBuilder.filter().add(QueryBuilders.rangeQuery("price").lte(999));
handleResponse(request);
}
@Test
void testPageAndSort() throws IOException {
SearchRequest request = new SearchRequest("hotel");
int page = 2;
int pageSize = 5;
request.source().query(QueryBuilders.matchAllQuery());
request.source().sort("price", SortOrder.ASC);
request.source().from((page - 1) * pageSize).size(pageSize);
handleResponse(request);
}
@Test
void testHighlight() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.matchQuery("all", "如家"));
request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
handleResponse(request);
}
private void handleResponse(SearchRequest request) throws IOException {
// 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] searchHits = response.getHits().getHits();
for (SearchHit searchHit : searchHits) {
String source = searchHit.getSourceAsString();
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
if (!CollectionUtils.isEmpty(highlightFields)) {
HighlightField field = highlightFields.get("name");
Text[] texts = field.getFragments();
System.out.println(texts[0].string());
}
HotelDoc hotelDoc = JSON.parseObject(source, HotelDoc.class);
Hotel hotel = new Hotel();
BeanUtils.copyProperties(hotelDoc, hotel);
String[] location = hotelDoc.getLocation().split(",");
hotel.setLatitude(location[0]);
hotel.setLongitude(location[1]);
System.out.println(hotel);
}
}
@BeforeEach
void setUp() {
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.249.131:9200")
));
}
@AfterEach
void tearDown() throws IOException {
client.close();
}
}