用以致学,最近搞数据地图项目,元数据存储到ElasticSearch(ES)中快速检索,需要用java操作ES,研究研究写个DEMO,备忘,有需要的同学也可以看看。
代码都放这了:https://github.com/clj198606061111/spring-boot2-elasticsearch-demo
分三种方式操作ES
- spring-data-elasticsearch
- elasticsearch-rest-client
- elasticsearch-rest-high-level-client
spring-data-elasticsearch
核心依赖
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.1.1</version>
</dependency>
springdata 操作ES的CRUD代码
public interface BookRepository extends ElasticsearchRepository<Book, String> {
/*
在Spring Data reppository支持直接按名字解析,但是起的方法名要按照一定的规则来取,解析的时候会
剥离以下的套词,然后对剩下的部分进行解析,查询的套词如下:find…By, read…By, query…By, count…By和get…By,
反正不管怎样,By后面就是实际查询条件的开始,一般都是基于实体的属性作条件,条件之间使用And或者Or来连接,比如
findBookByIdAndName, findBookByNameOrAuth
*/
Book findByName(String name);
List<Book> findByAuthor(String author);
Book findBookById(String id);
}
@Service
public class BookServiceImpl implements BookService {
@Resource
private BookRepository bookRepository;
public Book add(Book book) {
return bookRepository.save(book);
}
public Book update(Book book) {
Book bookR = bookRepository.findBookById(book.getId());
if (null == bookR) {
return book;
}
bookR.setAuthor(book.getAuthor());
bookR.setName(book.getName());
return bookRepository.save(bookR);
}
public boolean delById(String id) {
bookRepository.deleteById(id);
return true;
}
public Book getById(String id) {
return bookRepository.findBookById(id);
}
public Iterable<Book> findAll() {
Pageable pageable = PageRequest.of(1, 10);
return bookRepository.findAll(pageable);
}
@Override
public Page<Book> queryPage(Integer pageNum, Integer pageSize, Book book) {
//分页是从第0页开始的
Pageable pageable = PageRequest.of(pageNum, pageSize);
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
if (!ObjectUtils.isEmpty(book.getName())) {
builder.withQuery(QueryBuilders.matchQuery("name", book.getName()));
}
if (!ObjectUtils.isEmpty(book.getDesc())) {
builder.withQuery(QueryBuilders.matchQuery("desc", book.getDesc()));
}
builder.withPageable(pageable);
return bookRepository.search(builder.build());
}
}
elasticsearch-rest-client
核心依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.10.0</version>
</dependency>
java 低级rest客户端操作ES的CRUD代码
@Service
public class EsServiceImpl implements EsService {
private Logger logger = LoggerFactory.getLogger(EsServiceImpl.class);
@Resource
private RestClient client;
@Override
public Book edit(Book book) throws IOException {
// 构造HTTP请求,第一个参数是请求方法,第二个参数是服务器的端点,host默认是http://localhost:9200,
// endpoint直接指定为index/type的形式
Request request = new Request(HttpMethod.POST.name(), new StringBuilder("/book/_doc/").
append(book.getId()).toString());
// 设置其他一些参数比如美化json
request.addParameter("pretty", "true");
// 设置请求体并指定ContentType,如果不指定默认为TEXT_PLAIN,
//设置ContentType.APPLICATION_JSON,UTF-8格式,中文不会乱码
request.setEntity(new NStringEntity(JSON.toJSONString(book), ContentType.APPLICATION_JSON));
// 发送HTTP请求
Response response = client.performRequest(request);
// 获取响应体, id: AWXvzZYWXWr3RnGSLyhH
String responseBody = EntityUtils.toString(response.getEntity());
logger.info(responseBody);
return book;
}
@Override
public boolean delById(String id) throws IOException {
Request request = new Request(HttpMethod.DELETE.name(),
new StringBuilder("/book/_doc/").append(id).toString());
Response response = client.performRequest(request);
String responseBody = EntityUtils.toString(response.getEntity());
logger.info(responseBody);
return true;
}
@Override
public Book getById(String id) throws IOException {
Request request = new Request(HttpMethod.GET.name(),
new StringBuilder("/book/_doc/").append(id).toString());
Response response = client.performRequest(request);
String responseBody = EntityUtils.toString(response.getEntity());
logger.info(responseBody);
return EsUtil.pass(responseBody, Book.class);
}
@Override
public boolean update(String id, Book book) throws IOException {
// 构造HTTP请求
Request request = new Request("POST", new StringBuilder("/book/_doc/").
append(id).append("/_update").toString());
// 将数据丢进去,这里一定要外包一层“doc”,否则内部不能识别
JSONObject jsonObject = new JSONObject();
jsonObject.put("doc", book);
request.setEntity(new NStringEntity(jsonObject.toString(), ContentType.APPLICATION_JSON));
// 执行HTTP请求
Response response = client.performRequest(request);
// 获取返回的内容
String responseBody = EntityUtils.toString(response.getEntity());
logger.info(responseBody);
return true;
}
@Override
public boolean updateDescByScript(String id, String desc) throws IOException {
// 构造HTTP请求
Request request = new Request("POST", new StringBuilder("/book/_doc/").
append(id).append("/_update").toString());
JSONObject jsonObject = new JSONObject();
// 创建脚本语言,如果是字符变量,必须加单引号
StringBuilder op1 = new StringBuilder("ctx._source.desc=").append("'" + desc + "'");
jsonObject.put("script", op1);
request.setEntity(new NStringEntity(jsonObject.toString(), ContentType.APPLICATION_JSON));
// 执行HTTP请求
Response response = client.performRequest(request);
// 获取返回的内容
String responseBody = EntityUtils.toString(response.getEntity());
logger.info(responseBody);
return true;
}
@Override
public List<Book> queryByName(String name) throws IOException {
Request request = new Request("POST", new StringBuilder("/book/_doc/_search").toString());
JSONObject query = new JSONObject();
JSONObject match = new JSONObject();
JSONObject termName = new JSONObject();
termName.put("name", name);
match.put("match", termName);
query.put("query", match);
logger.info(JSON.toJSONString(query));
request.setEntity(new NStringEntity(JSON.toJSONString(query), ContentType.APPLICATION_JSON));
// 执行HTTP请求
Response response = client.performRequest(request);
// 获取返回的内容
String responseBody = EntityUtils.toString(response.getEntity());
logger.info(responseBody);
return null;
}
}
elasticsearch-rest-high-level-client
核心依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.0</version>
</dependency>
java 高级客户端操作ES的CRUD代码,个人感觉封装得有点复杂,还是需要非常熟悉ES的rest 低级接口才能容易理解并用高级客户端实现逻辑CRUD。
@Service
public class EsServiceImpl implements EsService {
@Resource
private RestHighLevelClient client;
private static final String INDEX_CITY = "city";
private static final String TYPE = "_doc";
@Override
public City add(City city) throws IOException {
client.index(new IndexRequest(INDEX_CITY).id(String.valueOf(city.getId())).source(JSON.toJSONString(city), XContentType.JSON), RequestOptions.DEFAULT);
return city;
}
@Override
public City update(City city) throws IOException {
client.update(new UpdateRequest(INDEX_CITY, String.valueOf(city.getId())).doc(new IndexRequest(INDEX_CITY).id(String.valueOf(city.getId())).source(JSON.toJSONString(city), XContentType.JSON)), RequestOptions.DEFAULT);
return city;
}
@Override
public boolean delById(Integer id) throws IOException {
client.delete(new DeleteRequest(INDEX_CITY).id(String.valueOf(id)), RequestOptions.DEFAULT);
return true;
}
@Override
public City getById(Integer id) throws IOException {
GetResponse response = client.get(new GetRequest(INDEX_CITY, String.valueOf(id)), RequestOptions.DEFAULT);
return JSON.parseObject(response.getSourceAsString(), City.class);
}
@Override
public List<City> queryByName(String name) throws IOException {
SearchRequest request = new SearchRequest();
request.scroll(new TimeValue(1, TimeUnit.HOURS)); //滚动游标保留多久
request.setBatchedReduceSize(10);//每批次拉多少条
request.indices(INDEX_CITY);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().must(QueryBuilders.prefixQuery("name", name));
PrefixQueryBuilder prefixQueryBuilder = QueryBuilders.prefixQuery("name", name);
sourceBuilder.query(prefixQueryBuilder);
sourceBuilder.timeout(TimeValue.timeValueMinutes(2L));
//sourceBuilder.size(10);//分页量
//sourceBuilder.sort("name", SortOrder.DESC);//排序
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
return Arrays.asList(response.getHits().getHits()).stream().map(obj -> JSON.parseObject(obj.getSourceAsString(), City.class)).collect(Collectors.toList());
}
}