本文以Java为例,测试功能为主,RestHighLevelClient客户端(已废弃)
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<properties>
<elasticsearch.version>7.17.21</elasticsearch.version>
</properties>
索引测试
前提
@SpringBootTest
class EsApplicationTests {
@Deprecated
private RestHighLevelClient client;
private static final String INDEX_NAME = "hotel";
@BeforeEach
@Deprecated
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.91.131:9200")));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
创建
@Test
void createIndexTest() throws IOException {
// 创建索引
CreateIndexRequest request = new CreateIndexRequest(INDEX_NAME);
// 设置索引的映射
String source = new String(Files.readAllBytes(Paths.get("data/es_mapping.json")));
request.source(source, XContentType.JSON);
// 发送请求
client.indices().create(request, RequestOptions.DEFAULT);
}
删除
@Test
void deleteIndexTest() throws IOException {
// 删除索引
DeleteIndexRequest request = new DeleteIndexRequest(INDEX_NAME);
// 发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
判断是否存在
@Test
void isExistIndexTest() throws IOException {
// 获取索引
GetIndexRequest request = new GetIndexRequest(INDEX_NAME);
// 发送请求
boolean flag = client.indices().exists(request, RequestOptions.DEFAULT);
// Assertions.assertTrue(flag);
Assertions.assertFalse(flag);
}
文档测试
新增
@Test
void addDocTest() throws IOException {
Hotel hotel = hotelService.getById(ID);
HotelDoc hotelDoc = new HotelDoc(hotel);
IndexRequest request = new IndexRequest(INDEX_NAME).id(hotelDoc.getId().toString());
request.source(new Gson().toJson(hotelDoc), XContentType.JSON);
client.index(request, RequestOptions.DEFAULT);
}
批量新增
@Test
void addByBatchDocTest() throws IOException {
BulkRequest request = new BulkRequest();
List<Hotel> hotelList = hotelService.list();
// for
for (Hotel hotel : hotelList) {
HotelDoc hotelDoc = new HotelDoc(hotel);
IndexRequest indexRequest = new IndexRequest(INDEX_NAME).id(hotelDoc.getId().toString());
indexRequest.source(new Gson().toJson(hotelDoc), XContentType.JSON);
request.add(indexRequest);
}
// lambda
hotelList.forEach(hotel -> request.add(new IndexRequest(INDEX_NAME).id(hotel.getId().toString()).source(new Gson().toJson(new HotelDoc(hotel)), XContentType.JSON)));
client.bulk(request, RequestOptions.DEFAULT);
}
删除
@Test
void deleteDocTest() throws IOException {
DeleteRequest request = new DeleteRequest(INDEX_NAME, String.valueOf(ID));
DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
}
修改
@Test
void updateDocTest() throws IOException {
UpdateRequest request = new UpdateRequest(INDEX_NAME, String.valueOf(ID));
request.doc(
"price", "444",
"score", "44"
);
client.update(request, RequestOptions.DEFAULT);
}
查询
@Test
void getDocTest() throws IOException {
GetRequest request = new GetRequest(INDEX_NAME, String.valueOf(ID));
String source = client.get(request, RequestOptions.DEFAULT).getSourceAsString();
HotelDoc hotelDoc = new Gson().fromJson(source, HotelDoc.class);
System.out.println(hotelDoc);
}
DSL测试
- 前提:处理搜索结果方法封装
private static class handleResponse {
public final long total;
public final ArrayList<HotelDoc> hotelDocList;
public handleResponse(long total, ArrayList<HotelDoc> hotelDocList) {
this.total = total;
this.hotelDocList = hotelDocList;
}
}
private handleResponse getHandleResponse(SearchRequest request) throws IOException {
SearchHits hits = client.search(request, RequestOptions.DEFAULT).getHits();
SearchHit[] searchHits = hits.getHits();
long total = hits.getTotalHits().value;
ArrayList<HotelDoc> hotelDocList = new ArrayList<>(searchHits.length);
for (SearchHit hit : searchHits) {
HotelDoc hotelDoc = new Gson().fromJson(hit.getSourceAsString(), HotelDoc.class);
// 高亮处理
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (!CollectionUtils.isEmpty(highlightFields)) {
String highLightHTML = highlightFields.get("name").getFragments()[0].toString();
hotelDoc.setName(highLightHTML);
}
hotelDocList.add(hotelDoc);
}
return new handleResponse(total, hotelDocList);
}
搜索所有
@Test
void matchAllTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
request.source().query(QueryBuilders.matchAllQuery());
handleResponse result = getHandleResponse(request);
System.out.println(result.total);
System.out.println(result.hotelDocList);
}
全文检索
- match
@Test
void matchTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
request.source().query(QueryBuilders.matchQuery("all", "如家"));
handleResponse result = getHandleResponse(request);
System.out.println(result.total);
System.out.println(result.hotelDocList);
}
- multi_match
@Test
void multiplyTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
request.source().query(QueryBuilders.multiMatchQuery("如家", "name", "brand", "business"));
handleResponse result = getHandleResponse(request);
System.out.println(result.total);
System.out.println(result.hotelDocList);
}
- term、range与match同理,只是参数变化
地理查询
- geo_distance
@Test
void geoDistanceTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
GeoDistanceQueryBuilder location = QueryBuilders.geoDistanceQuery("location");
location.distance("2", DistanceUnit.KILOMETERS);
location.point(31.21, 121.5);
request.source().query(location);
handleResponse result = getHandleResponse(request);
System.out.println(result.total);
System.out.println(result.hotelDocList);
}
- geo_bounding_box
@Test
void geoBoundingBoxTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
GeoBoundingBoxQueryBuilder location = QueryBuilders.geoBoundingBoxQuery("location");
location.setCorners(new GeoPoint(31.1, 121.5), new GeoPoint(30.9, 121.7));
request.source().query(location);
handleResponse result = getHandleResponse(request);
System.out.println(result.total);
System.out.println(result.hotelDocList);
}
复合查询
@Test
void boolTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.termQuery("city", "上海"));
boolQuery.filter(QueryBuilders.rangeQuery("price").lt(400));
request.source().query(boolQuery);
handleResponse result = getHandleResponse(request);
System.out.println(result.total);
System.out.println(result.hotelDocList);
}
结果返回
- order & pagination
@Test
void orderAndPaginationTest() throws IOException {
int pageNum = 2;
int pageSize = 5;
SearchRequest request = new SearchRequest(INDEX_NAME);
request.source().query(QueryBuilders.matchAllQuery()).from((pageNum - 1) * pageSize).size(pageSize).sort("price", SortOrder.ASC);
handleResponse result = getHandleResponse(request);
System.out.println(result.total);
System.out.println(result.hotelDocList);
}
- highlight
@Test
void highLightTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name").requireFieldMatch(false).preTags("<h1>").postTags("</h1>");
request.source().query(QueryBuilders.matchQuery("all", "如家")).highlighter(highlightBuilder).from(0).size(2);
handleResponse result = getHandleResponse(request);
System.out.println(result.total);
System.out.println(result.hotelDocList);
}
高级测试
- 方法封装
private List<? extends Terms.Bucket> aggregationHandle(String aggName, SearchResponse response) {
Terms aggResult = response.getAggregations().get(aggName);
return aggResult.getBuckets();
}
聚合
@Test
void aggregationTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
request.source().size(0);
String aggName = "brandAgg";
request.source().aggregation(AggregationBuilders.terms(aggName).field("brand").size(10));
SearchResponse result = client.search(request, RequestOptions.DEFAULT);
List<? extends Terms.Bucket> buckets = aggregationHandle(aggName, result);
buckets.forEach(bucket -> {
System.out.println(bucket.getKeyAsString() + " : " + bucket.getDocCount());
});
}
自定补全
@Test
void completeTest() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
String keyword = "北京";
String suggestName = "suggestions";
String suggestField = "suggestion";
request.source().suggest(new SuggestBuilder()
.addSuggestion(suggestName, SuggestBuilders.completionSuggestion(suggestField).prefix(keyword).skipDuplicates(true).size(10)));
SearchResponse result = client.search(request, RequestOptions.DEFAULT);
List<CompletionSuggestion.Entry.Option> options = suggestionHandle(suggestName, result);
options.forEach(option -> {
System.out.println(option.getText().string());
});
}
private List<? extends Terms.Bucket> aggregationHandle(String aggName, SearchResponse response) {
Terms aggResult = response.getAggregations().get(aggName);
return aggResult.getBuckets();
}