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> </jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir> <working-dir>$ProjectFileDir$</working-dir>
</data-source> </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> </component>
</project> </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"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="RemoteRepositoriesConfiguration"> <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> <remote-repository>
<option name="id" value="central" /> <option name="id" value="central" />
<option name="name" value="Maven Central repository" /> <option name="name" value="Maven Central repository" />
@ -16,5 +21,10 @@
<option name="name" value="Central Repository" /> <option name="name" value="Central Repository" />
<option name="url" value="https://maven.aliyun.com/repository/public" /> <option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository> </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> </component>
</project> </project>

View File

@ -1,13 +1,14 @@
package cn.itcast.hotel; package cn.itcast.hotel;
import com.baomidou.mybatisplus.annotation.DbType; import org.apache.http.HttpHost;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import org.elasticsearch.client.RestClient;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.elasticsearch.client.RestHighLevelClient;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@MapperScan("cn.itcast.hotel.mapper") @MapperScan("cn.itcast.hotel.mapper")
@SpringBootApplication @SpringBootApplication
public class HotelDemoApplication { public class HotelDemoApplication {
@ -16,4 +17,11 @@ public class HotelDemoApplication {
SpringApplication.run(HotelDemoApplication.class, args); 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 business;
private String location; private String location;
private String pic; private String pic;
private Object distance;
private Boolean isAd;
public HotelDoc(Hotel hotel) { public HotelDoc(Hotel hotel) {
this.id = hotel.getId(); 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; package cn.itcast.hotel.service;
import cn.itcast.hotel.pojo.Hotel; 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; import com.baomidou.mybatisplus.extension.service.IService;
public interface IHotelService extends IService<Hotel> { 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.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel; 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 cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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.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 @Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService { 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.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@SpringBootTest @SpringBootTest
@ -29,84 +31,63 @@ class HotelDocumentTest {
private RestHighLevelClient client; private RestHighLevelClient client;
@Autowired @Resource
private IHotelService hotelService; private IHotelService hotelService;
@Test @Test
void testAddDocument() throws IOException { void testAddDocument() throws IOException {
// 1.查询数据库hotel数据 Hotel hotel = hotelService.getById(56227L);
Hotel hotel = hotelService.getById(61083L);
// 2.转换为HotelDoc
HotelDoc hotelDoc = new HotelDoc(hotel); HotelDoc hotelDoc = new HotelDoc(hotel);
// 3.转JSON IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
String json = JSON.toJSONString(hotelDoc); request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
// 发送请求
// 1.准备Request
IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
// 2.准备请求参数DSL其实就是文档的JSON字符串
request.source(json, XContentType.JSON);
// 3.发送请求
client.index(request, RequestOptions.DEFAULT); client.index(request, RequestOptions.DEFAULT);
} }
@Test @Test
void testGetDocumentById() throws IOException { void testGetDocument() throws IOException {
// 1.准备Request // GET /hotel/_doc/{id} GetRequest request = new GetRequest("hotel", "56227");
GetRequest request = new GetRequest("hotel", "61083");
// 2.发送请求
GetResponse response = client.get(request, RequestOptions.DEFAULT); GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 3.解析响应结果 String source = response.getSourceAsString();
String json = response.getSourceAsString(); HotelDoc hotel = JSON.parseObject(source, HotelDoc.class);
System.out.println("hotel = " + hotel);
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println("hotelDoc = " + hotelDoc);
} }
@Test @Test
void testDeleteDocumentById() throws IOException { void testUpdateDocument() throws IOException {
// 1.准备Request // DELETE /hotel/_doc/{id} UpdateRequest updateRequest = new UpdateRequest("hotel", "56227");
DeleteRequest request = new DeleteRequest("hotel", "61083"); updateRequest.doc(
// 2.发送请求 "price", "999",
client.delete(request, RequestOptions.DEFAULT); "starName", "四钻"
}
@Test
void testUpdateById() throws IOException {
// 1.准备Request
UpdateRequest request = new UpdateRequest("hotel", "61083");
// 2.准备参数
request.doc(
"price", "870"
); );
// 3.发送请求 client.update(updateRequest, RequestOptions.DEFAULT);
client.update(request, RequestOptions.DEFAULT);
} }
@Test @Test
void testBulkRequest() throws IOException { void testDeleteDocument() throws IOException {
// 查询所有的酒店数据 DeleteRequest deleteRequest = new DeleteRequest("hotel", "56227");
List<Hotel> list = hotelService.list(); client.delete(deleteRequest, RequestOptions.DEFAULT);
}
// 1.准备Request
BulkRequest request = new BulkRequest(); @Test
// 2.准备参数 void testBulkDocument() throws IOException {
for (Hotel hotel : list) { BulkRequest bulkRequest = new BulkRequest();
// 2.1.转为HotelDoc List<Hotel> hotelList = hotelService.list();
for (Hotel hotel : hotelList) {
HotelDoc hotelDoc = new HotelDoc(hotel); HotelDoc hotelDoc = new HotelDoc(hotel);
// 2.2.转json bulkRequest.add(new IndexRequest("hotel")
String json = JSON.toJSONString(hotelDoc); .id(hotelDoc.getId().toString())
// 2.3.添加请求 .source(JSON.toJSONString(hotelDoc), XContentType.JSON));
request.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(json, XContentType.JSON));
} }
client.bulk(bulkRequest, RequestOptions.DEFAULT);
// 3.发送请求
client.bulk(request, RequestOptions.DEFAULT);
} }
@BeforeEach @BeforeEach
void setUp() { void setUp() {
client = new RestHighLevelClient(RestClient.builder( 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();
}
}