依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.2.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.2.0</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.2.0</version>
</dependency>
es操作类
/**
* es操作类
*/
public class EsHandler<T extends BaseEntity> {
private static final int FROM = 0;
private static final int SIZE = 50;
private static final String HOST = "192.168.1.66";
private static final int PORT = 9200;
private static final String SCHEME = "http";
private static final int CONNECTION_TIMEOUT = 4000;
private static final int SOCKET_TIMEOUT = 30000;
private static final int CONNECTION_REQUEST_TIMEOUT = 2000;
private static final int MAX_CONN_TOTAL = 100;
private static final int MAX_CONN_PER_ROUTE = 100;
private static final int IO_THREAD_COUNT = 10;
private static final RestHighLevelClient REST_HIGH_LEVEL_CLIENT;
static {
RestClientBuilder builder = RestClient.builder(new HttpHost(HOST, PORT, SCHEME));
// 异步httpclient的连接延时配置
builder.setRequestConfigCallback(configBuilder -> {
configBuilder.setConnectTimeout(CONNECTION_TIMEOUT);
configBuilder.setSocketTimeout(SOCKET_TIMEOUT);
configBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT);
return configBuilder;
});
CredentialsProvider provider = new BasicCredentialsProvider();
// 用户名密码验证,没有设置用户名密码则不进行配置
provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "Msx985211_TD"));
// httpclient的连接数,线程设置
builder.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setDefaultCredentialsProvider(provider);
httpClientBuilder.setMaxConnTotal(MAX_CONN_TOTAL);
httpClientBuilder.setMaxConnPerRoute(MAX_CONN_PER_ROUTE);
httpClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(IO_THREAD_COUNT).build());
return httpClientBuilder;
});
REST_HIGH_LEVEL_CLIENT = new RestHighLevelClient(builder);
}
/**
* 获取客户端连接
*/
public static RestHighLevelClient getRestHighLevelClient() {
return REST_HIGH_LEVEL_CLIENT;
}
/**
* 创建索引
*/
public void createIndex(String indexName) throws IOException {
if (isIndexExist(indexName)) {
return;
}
REST_HIGH_LEVEL_CLIENT.indices().create(new CreateIndexRequest(indexName).settings(Settings.EMPTY), RequestOptions.DEFAULT);
}
/**
* 删除索引
*/
public void deleteIndex(String indexName) throws IOException {
if (!isIndexExist(indexName)) {
return;
}
REST_HIGH_LEVEL_CLIENT.indices().delete(new DeleteIndexRequest(indexName), RequestOptions.DEFAULT);
}
/**
* 判断索引是否存在
*/
private boolean isIndexExist(String indexName) throws IOException {
return REST_HIGH_LEVEL_CLIENT.indices().exists(new GetIndexRequest(indexName), RequestOptions.DEFAULT);
}
/**
* 保存数据
*/
public void save(String index, T t) throws IOException {
if (isDataExist(index, t)) {
return;
}
REST_HIGH_LEVEL_CLIENT.index(new IndexRequest(index).id(t.getId()).source(JSON.toJSONString(t), XContentType.JSON), RequestOptions.DEFAULT);
}
// 批量保存数据
public void batchSave(String index, List<T> ts) throws IOException {
if (null == ts || ts.isEmpty()) {
return;
}
// 批量操作对象,可以将DeleteRequest、IndexRequest和UpdateRequest放在一起执行
BulkRequest request = new BulkRequest();
ts.forEach(t -> request.add(new IndexRequest(index).id(t.getId()).source(JSON.toJSONString(t), XContentType.JSON)));
REST_HIGH_LEVEL_CLIENT.bulk(request, RequestOptions.DEFAULT);
}
/**
* 更新数据
*/
public void update(String index, T t) throws IOException {
if (!isDataExist(index, t)) {
return;
}
UpdateRequest request = new UpdateRequest().index(index).id(t.getId()).doc(JSON.toJSONString(t), XContentType.JSON);
REST_HIGH_LEVEL_CLIENT.update(request, RequestOptions.DEFAULT);
}
/**
* 删除数据
*/
public void delete(String index, String id) throws IOException {
DeleteRequest request = new DeleteRequest(index).id(id);
REST_HIGH_LEVEL_CLIENT.delete(request, RequestOptions.DEFAULT);
}
/**
* 判断数据是否存在
*/
private boolean isDataExist(String index, T t) throws IOException {
GetRequest request = new GetRequest(index).id(t.getId());
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
return REST_HIGH_LEVEL_CLIENT.exists(request, RequestOptions.DEFAULT);
}
/**
* 根据id查询
*/
public T query(String index, T t) throws IOException {
GetRequest request = new GetRequest(index).id(t.getId());
return JSON.parseObject(REST_HIGH_LEVEL_CLIENT.get(request, RequestOptions.DEFAULT).getSourceAsString(), (Class<T>) t.getClass());
}
/**
* 分页查询
*/
public Page<T> queryPage(String index, T t) throws IOException {
Page<T> page = t.getPage();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(getBoolQueryBuilder(t));
searchSourceBuilder.from(t.getPage().getPageNo()).size(t.getPage().getPageSize());
SearchRequest request = new SearchRequest(index).source(searchSourceBuilder);
SearchHits searchHits = REST_HIGH_LEVEL_CLIENT.search(request, RequestOptions.DEFAULT).getHits();
page.setTotal(searchHits.getTotalHits().value);
Iterator<SearchHit> searchHitIterator = searchHits.iterator();
List<T> list = new ArrayList<>();
page.setList(list);
while (searchHitIterator.hasNext()) {
String json = searchHitIterator.next().getSourceAsString();
System.out.println(json);
list.add(JSON.parseObject(json, (Class<T>) t.getClass()));
}
return page;
}
/**
* 条件查询
*/
public List<T> queryCondition(String index, T t) throws IOException {
if (null == t.getPage()) {
Page<T> page = new Page<>();
page.setPageNo(FROM);
page.setPageSize(SIZE);
t.setPage(page);
}
Page<T> page = queryPage(index, t);
return page.getList();
}
public void closeClient() {
try {
REST_HIGH_LEVEL_CLIENT.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private BoolQueryBuilder getBoolQueryBuilder(T t) {
BoolQueryBuilder builder = new BoolQueryBuilder();
if (null != t.getExtension() && !t.getExtension().isEmpty()) {
// 内容匹配
if (null != t.getExtension().get(BaseEntity.MATCH)) {
t.getExtension().get(BaseEntity.MATCH).forEach((k, v) -> builder.must(QueryBuilders.matchQuery(k, v)));
}
// 精确匹配
if (null != t.getExtension().get(BaseEntity.TERM)) {
t.getExtension().get(BaseEntity.TERM).forEach((k, v) -> builder.must(QueryBuilders.termQuery(k, v)));
}
// 前缀匹配
if (null != t.getExtension().get(BaseEntity.PREFIX)) {
t.getExtension().get(BaseEntity.PREFIX).forEach((k, v) -> builder.must(QueryBuilders.matchPhrasePrefixQuery(k, v).maxExpansions(500000)));
}
// 关键字匹配
if (null != t.getExtension().get(BaseEntity.WILD)) {
t.getExtension().get(BaseEntity.WILD).forEach((k, v) -> builder.must(QueryBuilders.wildcardQuery(k, v)));
}
}
// 多字段匹配匹配
if (null != t.getMulExtension() && !t.getMulExtension().isEmpty()) {
t.getMulExtension().forEach((k, v) -> builder.must(QueryBuilders.multiMatchQuery(k, v.toArray(new String[v.size()]))));
}
// 范围匹配
if (null != t.getRangeExtension() && !t.getRangeExtension().isEmpty()) {
t.getRangeExtension().forEach((k, v) -> builder.must(QueryBuilders.rangeQuery(k).gte(v.get(0)).lte(v.get(1))));
}
return builder;
}
}
实体类
/**
* 基础实体类
*/
@Data
public abstract class BaseEntity implements Serializable {
private String id;
/**
* 模糊匹配和精确匹配扩展字段
*/
private Map<String, Map<String, String>> extension;
/**
* 多字段匹配扩展字段
*/
private Map<String, List<String>> mulExtension;
/**
* 范围匹配扩展字段
*/
private Map<String, List<Object>> rangeExtension;
private Page page;
public static final String MATCH = "match";
public static final String TERM = "term";
public static final String WILD = "wild";
public static final String PREFIX = "prefix";
}
/**
* 建筑类
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class Building extends BaseEntity {
/**
* 建筑名称,可用于模糊匹配
*/
private String name;
/**
* 建筑分类:框架结构,剪力墙结构,钢结构......可用于精确匹配,关键字匹配
*/
private String type;
/**
* 建筑地理位置,可用于模糊匹配
*/
private String location;
/**
* 建筑高度,可用于范围查询
*/
private double height;
private double[] center;
enum BuildingType {
STRUCTURE_FRAME("框架结构"),
STRUCTURE_SHEAR_WALL("剪力墙结构"),
STRUCTURE_STEEL("钢结构");
private String name;
BuildingType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
测试类
public class Test {
private static final String INDEX_NAME = "project_building";
public static void main(String[] args) {
EsHandler<Building> esHandler = new EsHandler<>();
try {
// 测试批量添加
esHandler.batchSave(INDEX_NAME, getBuildings());
String id = "2bde0d1c-c44b-4482-9b53-190dcf1b9db3";
Building building = new Building();
building.setId(id);
// 查询对象
building = esHandler.query(INDEX_NAME, building);
building.setName("测试修改建筑");
// 修改对象
esHandler.update(INDEX_NAME, building);
// 删除对象
esHandler.delete(INDEX_NAME, id);
// 条件查询对象
building = new Building();
Map<String, Map<String, String>> extension = new HashMap<>();
Map<String, String> match = new HashMap<>();
match.put("name", "上海中心");
extension.put(BaseEntity.MATCH, match);
building.setExtension(extension);
esHandler.queryCondition(INDEX_NAME, building);
} catch (IOException e) {
e.printStackTrace();
} finally {
esHandler.closeClient();
}
}
}