1)引入es的RestHighLevelClient依赖:
org.elasticsearch.client
elasticsearch-rest-high-level-client
2)因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:
1.8
7.12.1
3)初始化RestHighLevelClient:
初始化的代码如下:
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.150.101:9200")
));
存储的是新增索引库的语句
package cn.itcast.hotel;
public class HotelConstants {
public static final String MAPPING_TEMPLATE = "{\n" +
" \"mappings\": {\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"name\":{\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"address\":{\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"price\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"score\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"brand\":{\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"city\":{\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"starName\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"business\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"location\":{\n" +
" \"type\": \"geo_point\"\n" +
" },\n" +
" \"pic\":{\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"all\":{\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
}
新增和删除索引库操作
import org.apache.http.HttpHost;
import org.apache.http.client.methods.HttpPost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
class HotelSuoYinTest {
private RestHighLevelClient client;
@BeforeEach
void setup() {
this.client =
new RestHighLevelClient(
RestClient.builder(
HttpHost.create("http://101.43.94.150:9200")
));
}
@AfterEach
void shutdown() throws IOException {
this.client.close();
}
// indices() 有这个,就是索引库的操作
@Test
void test() throws IOException {
// 创建request对象
CreateIndexRequest request = new CreateIndexRequest("hotel");
// 准备请求的参数 dsl语句
request.source(HotelConstants.MAPPING_TEMPLATE, XContentType.JSON);
// 发送请求
client.indices().create(request, RequestOptions.DEFAULT);
}
@Test
void deltest() throws IOException {
// 创建request对象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
}
判断索引库是不是存在
@Test
void testExistsHotelIndex() throws IOException {
// 1.创建Request对象
GetIndexRequest request = new GetIndexRequest("hotel");
// 2.发送请求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
// 3.输出
System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
}
索引库操作的基本步骤:
初始化RestHighLevelClient
创建XxxIndexRequest。XXX是Create、Get、Delete
准备DSL( Create时需要,其它是无参)
发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete
因为mysql查询出来的hotel信息经纬度信息是分开的,但是eleasticsearch的地理坐标要求是一个String类型,中间用逗号分开,所以要转为hotelDoc
//文档,相当于mysql中的行
//#查询一条文档(记录)的 dsl语句
// GET /heima/_doc/1
@SpringBootTest
public class DocumentTest {
private RestHighLevelClient client;
@Autowired
HotelService hotelService;
// 插入新数据
@Test
public void testadd() throws IOException {
Hotel hotel = hotelService.getById(61083L);
HotelDoc hotelDoc = new HotelDoc(hotel);
// 创建request,并指明要处理的索引是hotel,记录号是 hotelDoc.getId()
IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
client.index(request, RequestOptions.DEFAULT);
}
// 查询某条数据
@Test
public void testquery() throws IOException {
GetRequest request = new GetRequest("hotel", "61083");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}
//更新某条数据
@Test
public void testupdate() throws IOException {
Hotel hotel = hotelService.getById(61083L);
HotelDoc hotelDoc = new HotelDoc(hotel);
UpdateRequest request = new UpdateRequest("hotel", "61083");
request.doc("price", "952");
request.doc("address", "北京饭店");
client.update(request, RequestOptions.DEFAULT);
}
// 删除某条数据
@Test
void testDeleteDocument() throws IOException {
// 1.准备Request
DeleteRequest request = new DeleteRequest("hotel", "61083");
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
}
@Test
void testpiliangadd() throws IOException {
List hotels = hotelService.list();
BulkRequest request = new BulkRequest();
for (Hotel hotel : hotels) {
HotelDoc hotelDoc = new HotelDoc(hotel);
request.add(new IndexRequest("hotel")
.id(hotelDoc.getId() + "")
.source(JSON.toJSONString(hotelDoc)
, XContentType.JSON));
}
client.bulk(request, RequestOptions.DEFAULT);
}
@BeforeEach
void setup() {
this.client =
new RestHighLevelClient(
RestClient.builder(
HttpHost.create("http://101.43.94.150:9200")
));
}
@AfterEach
void shutdown() throws IOException {
this.client.close();
}
}
package cn.itcast.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.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
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.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.Map;
@SpringBootTest
public class QueryTest {
private RestHighLevelClient client;
//查询全部文档
@Test
void testmatchall() throws IOException {
// 1. 准备request
SearchRequest request = new SearchRequest("hotel");
// 2. 准备dsl
request.source().query(QueryBuilders.matchAllQuery());
// 3.发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
handleResponse(response);
}
//全文检索查询
@Test
void testquerycheck() throws IOException {
// 1. 准备request
SearchRequest request = new SearchRequest("hotel");
// 2. 准备dsl
request.source().query(QueryBuilders.matchQuery("all", "如家"));
// 3.发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
handleResponse(response);
}
//boolean复合查询
@Test
void testBool() throws IOException {
// 1.准备Request
SearchRequest request = new SearchRequest("hotel");
// 2.准备DSL
// 2.1.准备BooleanQuery
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 2.2.添加term
boolQuery.must(QueryBuilders.termQuery("city", "上海"));
// 2.3.添加range
boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));
// 关联查询条件
request.source().query(boolQuery);
// 3.发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.解析响应
handleResponse(response);
}
//查询后排序和按页查询 el的分页查询是查询所有结果之后再分页。
@Test
void testpageandsort() throws IOException {
// 页码,每页大小
int pagenum = 1, pagesize = 5;
// 1.准备Request
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.matchAllQuery());
request.source().sort("price", SortOrder.ASC);
// 前端传过来的是页码和每页大小 ,算一下从第多少条后开始分页
request.source().from((pagenum - 1) * pagesize);
// 页大小
request.source().size(pagesize);
// 3.发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.解析响应
handleResponse(response);
}
//查询后高亮显示
@Test
void testhightlight() throws IOException {
// 1.准备Request
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.matchQuery("brand", "如家"));
// requireFieldMatch(false) 搜索条件brand和高亮的属性name设为不一致
request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
// 3.发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
handleHeightLightResponse(response);
}
// 高亮查询
private void handleHeightLightResponse(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) {
// 获取文档source
String json = hit.getSourceAsString();
// 反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
// 获取高亮
Map highlightFields = hit.getHighlightFields();
HighlightField highlightField = highlightFields.get("name");
String name = highlightField.getFragments()[0].toString();
hotelDoc.setName(name);
System.out.println(hotelDoc);
}
}
// 解析响应函数
private 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) {
// 获取文档source
String json = hit.getSourceAsString();
// 反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
// System.out.println("hotelDoc = " + hotelDoc);
}
}
@BeforeEach
void setup() {
this.client =
new RestHighLevelClient(
RestClient.builder(
HttpHost.create("http://101.43.94.150:9200")
));
}
@AfterEach
void shutdown() throws IOException {
this.client.close();
}
}