RestHighLevelClient实现搜索引擎
一、前言
海量数据的情况下,SQL中的模糊查询%s%会导致索引失效,但是业务场景需要根据某些字段进行查询。
搜索引擎会为数据添加索引,并且支持模糊查询,范围查询,精确查询
所以海量数据的全文搜索,最好是用搜索引擎来进行实现。
以下是开源搜索引擎elasticsearch的 RestHighLevelClient简单工具实现,添加数据获取数据全部使用json操作
二、使用步骤
1.pom文件和配置文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.14.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.14.0</version>
</dependency>
elasticsearch.ip=127.0.0.1
elasticsearch.port=9200
2.配置类
package com.mabo.elasticsearch;
import org.apache.http.HttpHost;
import org.elasticsearch.client.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ElasticSearchConfig {
@Value("${elasticsearch.ip}")
private String ip;
@Value("${elasticsearch.port}")
private String port;
/**
* 创建单例模式的RequestOptions,使得所有请求共用
*/
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
COMMON_OPTIONS = builder.build();
}
@Bean
public RestHighLevelClient client() {
RestClientBuilder builder=RestClient.builder(new HttpHost(ip, Integer.valueOf(port), "http"));
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
3.工具类
package com.roc.core.utils.elasticsearch;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.roc.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;
@Component
@Slf4j
public class ElasticsearchUtils {
@Autowired
private RestHighLevelClient restHighLevelClient;
public String addDocument(JSONObject params,String index,String idName) throws IOException {
IndexRequest indexRequest = new IndexRequest(index);
indexRequest.id(params.getString(idName));
// 将我们的数据放入请求 json
indexRequest.source(params, XContentType.JSON);
// 客户端发送请求
IndexResponse index1 = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
/**
* @Description : CREATED 新增成功
* OK,更新成功
* @Author : mabo
*/
return index1.status().toString();
}
/**
* 根据id
* 获取文档
* @throws IOException
*/
public JSONObject getDocumentById(String index, String id) {
GetRequest getRequest = new GetRequest(index, id);
GetResponse getResponse = null;
try {
getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error(e.getMessage(),e);
return null;
}
Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
if (sourceAsMap!=null){
return new JSONObject(sourceAsMap);
}
else {
return null;
}
}
/**
* 获取文档
* @throws IOException
*/
public JSONArray getDocument(int from,int size,String index) throws IOException {
SearchRequest searchRequest=new SearchRequest(index);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(from).size(size);
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(searchSourceBuilder);
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
JSONArray array = new JSONArray();
SearchHits hits = response.getHits();
for (SearchHit searchHit : hits) {
Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
JSONObject json = new JSONObject(sourceAsMap);
array.add(json);
}
return array;
}
/**
* 删除文档
*/
public boolean deleteDodument(String index, String id) throws IOException {
JSONObject documentById = getDocumentById(index, id);
if (documentById ==null){
return true;
}
DeleteRequest deleteRequest = new DeleteRequest(index, id);
DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
String s = delete.status().toString();
if (s.equals("OK")){
return true;
}
else {
return false;
}
}
/**
* 删除索引
* @param index
* @return
* @throws IOException
*/
public boolean deleteAllDodument(String index) throws IOException {
DeleteIndexRequest deleteRequest = new DeleteIndexRequest(index);
AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteRequest, RequestOptions.DEFAULT);
return delete.isAcknowledged();
}
/**
* @Description : 模糊查询
* @Author : mabo
*/
public JSONArray fuzzySearch(int from,int size,String index, String value, String... fieldName) throws IOException {
SearchRequest searchRequest=new SearchRequest(index);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(from).size(size);
searchSourceBuilder.query(QueryBuilders.multiMatchQuery(value,fieldName));
searchRequest.source(searchSourceBuilder);
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
JSONArray array = new JSONArray();
SearchHits hits = response.getHits();
for (SearchHit searchHit : hits) {
Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
JSONObject json = new JSONObject(sourceAsMap);
array.add(json);
}
return array;
}
/**
* @Description : 范围查询
* @Author : mabo
*/
public JSONArray rangeSearch(int from,int size,String index, String max,String min, String fieldName) throws IOException {
SearchRequest searchRequest=new SearchRequest(index);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(from).size(size);
searchSourceBuilder.query(QueryBuilders.rangeQuery(fieldName).from(min).to(max));
searchRequest.source(searchSourceBuilder);
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
JSONArray array = new JSONArray();
SearchHits hits = response.getHits();
for (SearchHit searchHit : hits) {
Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
JSONObject json = new JSONObject(sourceAsMap);
array.add(json);
}
return array;
}
/**
* @Description : 模糊查询
* @Author : mabo
*/
public JSONArray fuzzySearchSeal(int from,int size,String index, String value, String fieldName) throws IOException {
SearchRequest firstSearchRequest=new SearchRequest(index);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(from).size(size);
searchSourceBuilder.query(QueryBuilders.multiMatchQuery(value,"goodName","detail"));
firstSearchRequest.source(searchSourceBuilder);
//搜索
SearchResponse search = restHighLevelClient.search(firstSearchRequest, RequestOptions.DEFAULT);
JSONArray array = new JSONArray();
SearchHit[] hits = search.getHits().getHits();
for (SearchHit searchHit : hits) {
Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
JSONObject json = new JSONObject(sourceAsMap);
array.add(json);
}
return array;
}
/**
* @Description : 多条件模糊查询
* @Author : mabo
*/
public JSONArray fuzzyMultiSearch(int from,int size, String goodName,
Double latitudeMin,Double latitudeMax,
Double longitudeMin,Double longitudeMax,
Double sealMoneyMin,Double sealMoneyMax) throws IOException {
//设置索引
SearchRequest searchRequest = new SearchRequest("sealinfo");
//构建查询
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
RangeQueryBuilder latitudeBuilder = QueryBuilders.rangeQuery("latitude").from(latitudeMin).to(latitudeMax);
RangeQueryBuilder longitudeBuilder = QueryBuilders.rangeQuery("longitude").from(longitudeMin).to(longitudeMax);
boolBuilder = boolBuilder.must(latitudeBuilder);
boolBuilder = boolBuilder.must(longitudeBuilder);
if (!StringUtils.isBlank(goodName)){
MultiMatchQueryBuilder goodNameBuilder = QueryBuilders.multiMatchQuery(goodName, "goodName", "detail");
boolBuilder = boolBuilder.must(goodNameBuilder);
}
if (sealMoneyMin>0&&sealMoneyMax>0){
RangeQueryBuilder sealMoney = QueryBuilders.rangeQuery("sealMoney").from(sealMoneyMin).to(sealMoneyMax);
boolBuilder = boolBuilder.must(sealMoney);
}
sourceBuilder.from(from).size(size);
sourceBuilder.query(boolBuilder);
searchRequest.source(sourceBuilder);
//发送请求
SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
JSONArray array = new JSONArray();
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
JSONObject json = new JSONObject(sourceAsMap);
String allow = json.getString("allow");
String tradeType = json.getString("tradeType");
if (allow.equals("1")&&tradeType.equals("2")){
array.add(json);
}
}
return array;
}
}