一、导包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
二、yml配置
es:
ip:
port:
username:
password:
三、配置文件
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.ssl.SSLContextBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@Configuration
@Slf4j
public class ESClientConfig {
@Value("${es.ip}")
private String esIp;
@Value("${es.port}")
private Integer port;
@Value("${es.username}")
private String username;
@Value("${es.password}")
private String password;
/**
* 注册 rest高级客户端
* @date 2024/3/5 16:01
**/
@Bean
public RestHighLevelClient restHighLevelClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
// 创建CredentialsProvider,并设置用户名密码
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(username, password));
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial((chain, authType) -> true)
.build();
// 创建RestHighLevelClient实例,并设置CredentialsProvider
return new RestHighLevelClient(
RestClient.builder(new HttpHost(esIp, port, "https"))
.setHttpClientConfigCallback(httpAsyncClientBuilder ->
httpAsyncClientBuilder
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setSSLContext(sslContext)
.setDefaultCredentialsProvider(credentialsProvider)
) .setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder
.setConnectTimeout(5000)
.setSocketTimeout(60000))
);
}
}
四、操作
方式1:采用 RestHighLeveClient,封装一些常用操作,直接调用
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
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.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class RestHighLevelServiceImpl {
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 判断索引是否存在
*/
public Boolean indexExists(String indexName) throws Exception {
GetIndexRequest request = new GetIndexRequest(indexName);
return restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
}
/**
* 创建 ES 索引
*/
public CreateIndexResponse createIndex(String indexName, Settings.Builder settings, XContentBuilder mappings) throws Exception {
//将 Settings 和 Mappings 封装到一个Request 对象中
CreateIndexRequest request = new CreateIndexRequest(indexName)
.settings(settings)
.mapping(mappings);
//通过 client 对象去连接ES并执行创建索引
return restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
}
/**
* 批量创建 ES 文档
*/
public IndexResponse createDoc(String indexName, String id, String json) throws Exception {
//准备一个Request对象
IndexRequest request = new IndexRequest(indexName);
//手动指定ID
request.id(id);
request.source(json, XContentType.JSON);
//request.opType(DocWriteRequest.OpType.INDEX); 默认使用 OpType.INDEX,如果 id 重复,会进行 覆盖更新, resp.getResult().toString() 返回 UPDATE
//request.opType(DocWriteRequest.OpType.CREATE); 如果ID重复,会报异常 => document already exists
//通过 Client 对象执行添加
return restHighLevelClient.index(request, RequestOptions.DEFAULT);
}
/**
* 批量创建 ES 文档
*
* @param jsonMap Key = id,Value = json
*/
public BulkResponse batchCreateDoc(String indexName, Map<String, String> jsonMap) throws Exception {
//准备一个Request对象
BulkRequest bulkRequest = new BulkRequest();
for (String id : jsonMap.keySet()) {
IndexRequest request = new IndexRequest(indexName)
//手动指定ID
.id(id)
.source(jsonMap.get(id), XContentType.JSON);
bulkRequest.add(request);
}
//通过 Client 对象执行添加
return restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
}
/**
* 自动补全 根据用户的输入联想到可能的词或者短语
*
* @param indexName 索引名称
* @param field 搜索条件字段
* @param keywords 搜索关键字
* @param size 匹配数量
* @return
* @throws Exception
*/
public List<String> suggest(String indexName, String field, String keywords, int size) throws Exception {
//定义返回
List<String> suggestList = new ArrayList<>();
//构建查询请求
SearchRequest searchRequest = new SearchRequest(indexName);
//通过查询构建器定义评分排序
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//构造搜索建议语句,搜索条件字段
CompletionSuggestionBuilder completionSuggestionBuilder = new CompletionSuggestionBuilder(field);
//搜索关键字
completionSuggestionBuilder.prefix(keywords);
//去除重复
completionSuggestionBuilder.skipDuplicates(true);
//匹配数量
completionSuggestionBuilder.size(size);
searchSourceBuilder.suggest(new SuggestBuilder().addSuggestion("article-suggest", completionSuggestionBuilder));
//article-suggest为返回的字段,所有返回将在article-suggest里面,可写死,sort按照评分排序
searchRequest.source(searchSourceBuilder);
//定义查找响应
SearchResponse suggestResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//定义完成建议对象
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("article-suggest");
List<CompletionSuggestion.Entry.Option> optionsList = completionSuggestion.getEntries().get(0).getOptions();
//从optionsList取出结果
if (!CollectionUtils.isEmpty(optionsList)) {
optionsList.forEach(item -> suggestList.add(item.getText().toString()));
}
return suggestList;
}
/**
* 前缀查询,可以通过一个关键字去指定一个Field的前缀,从而查询到指定的文档
*/
public SearchResponse prefixQuery(String indexName, String searchField, String searchKeyword) throws Exception {
//创建Request对象
SearchRequest request = new SearchRequest(indexName);
//XX开头的关键词查询
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.prefixQuery(searchField, searchKeyword));
request.source(builder);
//执行查询
return restHighLevelClient.search(request, RequestOptions.DEFAULT);
}
/**
* 通过 QueryBuilder 构建多字段匹配如:QueryBuilders.multiMatchQuery("人工智能","title","content")
* multi_match => https://www.cnblogs.com/vipsoft/p/17164544.html
*/
public SearchResponse search(String indexName, QueryBuilder query, int currPage, int pageSize) throws Exception {
SearchRequest request = new SearchRequest(indexName);
SearchSourceBuilder builder = new SearchSourceBuilder();
int start = (currPage - 1) * pageSize;
builder.from(start);
builder.size(pageSize);
builder.query(query);
request.source(builder);
return restHighLevelClient.search(request, RequestOptions.DEFAULT);
}
}
方式2:采用 ElasticSearchRepositpry 进行查询
编写与ES索引对应的实体
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "bep20",createIndex = false)
public class Bep20 extends BaseDomain{
@Id
@ApiModelProperty(value="主键id")
private String id;
@JsonProperty("token_address")
@Field(name="token_address",type = FieldType.Keyword)
private String tokenAddress;
@JsonProperty("token_name")
@Field(name="token_name",type = FieldType.Text)
private String tokenName;
@Field(type = FieldType.Keyword)
private String precision;
@JsonProperty("from_address")
@Field(name="from_address",type = FieldType.Keyword)
private String fromAddress;
@JsonProperty("to_address")
@Field(name="to_address",type = FieldType.Keyword)
private String toAddress;
}
继承 ElasticsearchRepository,在接口里面直接写方法,方法不需要实现(底层会自动实现),方法直接调用即可,参数PageRequest用于分页,默认只能查询10条数据。
import com.jl.tfs.domain.Bep20;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface Bep20Repository extends ElasticsearchRepository<Bep20,String>{
List<Bep20> findBep20ByFromAddress(String address, PageRequest pageRequest);
List<Bep20> findBep20ByToAddress(String address,PageRequest pageRequest);
}
写方法时会自动提示
具体调用
list = bep20Repository.findBep20ByToAddress(address, PageRequest.of(0, 5000));