Api Client 选择创建客户端索引操作
添加索引 - 方式一添加索引二 文档操作
CRUD
插入文档获取文档删除文档修改文档 文档搜索
分页搜索简单搜索高亮搜索
Api Client 选择| 客户端 | 优点 | 缺点 | 说明 |
|---|---|---|---|
| Java Low Level Rest Client | 与ES版本之间没有关系,适用于作为所有版本ES的客户端 | ||
| Java High Level Rest Client | 使用最多 | 使用需与ES版本保持一致 | 基于Low Level Rest Client,注意:7.15版本之后将被弃用 |
| TransportClient | 使用Transport 接口进行通信,能够使用ES集群中的一些特性,性能最好 | JAR包版本需与ES集群版本一致,ES集群升级,客户端也跟着升级到相同版本 | 过时产品,7版本之后不再支持 |
| Elasticsearch Java API Client | 最新的es客户端 | 文档少 |
最稳方案:Java High Level Rest Client
官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html
spring starter官方依赖版本信息:https://docs.spring.io/spring-data/elasticsearch/docs/3.2.4.RELEASE/reference/html/#elasticsearch.versions
spring 官方对es的支持:https://docs.spring.io/spring-data/elasticsearch/docs/3.2.4.RELEASE/reference/html/#reference
ElasticSearch组件RestHighLevelClient用法详解:https://juejin.cn/post/6921479614304878599
注意:因为 Java High Level Rest Client 在使用的时候版本必须高度统一,springboot提供的starter:spring-data-elasticsearch 依赖版本是跟随springboot走,我们如果想要统一 es服务、分词器、api 客户端,最好是不使用官方 starter ,手动导入 Java High Level Rest Client 的pom依赖;
以下文档基于es 7.7.0,只给出关键的pom,部分api根据版本略有不同
创建客户端...... 7.7.0 org.elasticsearch elasticsearch ${elasticsearch.version} org.elasticsearch.client elasticsearch-rest-high-level-client ${elasticsearch.version} com.alibaba fastjson 1.2.75
@Configuration
public class HighLevelClientConfig {
@Bean(destroyMethod = "close")
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("ip:xxx.xxx.xxx.xxx", 9200, "http")));
return client;
}
}
索引操作 添加索引 - 方式一RestClient.builder 的参数是个可变参数,集群模式下,增加节点配置即可(多个new HttpHost)
使用客户端的时候注入即可,下文中所有esClient都来自这个类
特点:方便,不用每次设置分词器
private static Map添加索引二fieldAttr(EsFieldTypeEnum type) { Map result = new HashMap<>(); result.put("type", type.k); if ("text".equals(type.k)) { result.put("analyzer", "ik_max_word"); result.put("search_analyzer", "ik_max_word"); // result.put("ignore_above", ""); result.put("term_vector", "with_positions_offsets"); } return result; } public void createIndexM1() { try { String IndexName = "test_index_create_1"; CreateIndexRequest createIndexRequest = new CreateIndexRequest(IndexName); Map properties = new HashMap<>(); properties.put("id", fieldAttr(EsFieldTypeEnum.FIELD_INTEGER)); properties.put("title", fieldAttr(EsFieldTypeEnum.FIELD_TEXT)); properties.put("tag", fieldAttr(EsFieldTypeEnum.FIELD_KEYWORD)); properties.put("content", fieldAttr(EsFieldTypeEnum.FIELD_TEXT)); Map mapping = new HashMap<>(); mapping.put("properties", properties); createIndexRequest.mapping(mapping); createIndexRequest.settings( Settings.builder() .put("index.number_of_shards", 3) .put("index.number_of_replicas", 2)); CreateIndexResponse createIndexResponse = esClient.indices().create(createIndexRequest, RequestOptions.DEFAULT); boolean acknowledged = createIndexResponse.isAcknowledged(); log.info("acknowledged:{}", acknowledged); boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged(); log.info("shardsAcknowledged:{}", shardsAcknowledged); } catch (IOException e) { log.error(e.getMessage(), e); } }
特点:和请求体查询高度相似,灵活度高,方便控制每个字段的属性,但是写法比较繁琐
public void createIndexM2() {
try {
String indexName = "test_index_create_2";
CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject()
.startObject("mappings").startObject("properties")
.startObject("id")
.field("type", EsFieldTypeEnum.FIELD_INTEGER.k)
.endObject()
.startObject("title")
.field("type", EsFieldTypeEnum.FIELD_TEXT.k)
.field("analyzer","ik_max_word")
.field("search_analyzer","ik_smart")
.endObject()
.startObject("tag")
.field("type", EsFieldTypeEnum.FIELD_KEYWORD.k)
.endObject()
.startObject("content")
.field("type", EsFieldTypeEnum.FIELD_TEXT.k)
.field("analyzer","ik_max_word")
.field("search_analyzer","ik_smart")
.endObject()
.endObject().endObject()
.startObject("settings")
.field("number_of_shards",3)
.field("number_of_replicas",1)
.endObject()
.endObject();
createIndexRequest.source(builder);
CreateIndexResponse createIndexResponse = esClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
boolean acknowledged = createIndexResponse.isAcknowledged();
log.info("acknowledged:{}", acknowledged);
boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();
log.info("shardsAcknowledged:{}", shardsAcknowledged);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
文档操作
CRUD
插入文档
public void insertDoc() {
try {
String indexName = "test_index_create_2";
int id = 12;
Article article = new Article();
article.setId(id);
article.setTitle("java是世界上最好的语言");
article.setTag("语言");
article.setContent("程序员们放下手里的鼠标和键盘,抄起凳子打了起来");
IndexRequest indexRequest = new IndexRequest(indexName);
indexRequest.id(String.valueOf(id));
indexRequest.source(JSON.toJSONString(article), XContentType.JSON);
IndexResponse indexResponse = esClient.index(indexRequest, RequestOptions.DEFAULT);
log.info("indexResponse: " + JSON.toJSONString(indexResponse));
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
获取文档
public void getDoc() {
try {
String indexName = "test_index_create_2";
String id = "123";
GetRequest request = new GetRequest(indexName, id);
GetResponse response = esClient.get(request, RequestOptions.DEFAULT);
if (response.isExists()) {
String sourceAsString = response.getSourceAsString();
log.info("source: " + sourceAsString);
}
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
删除文档
public void deleteDoc() {
try {
String indexName = "test_index_create_2";
String id = "123";
DeleteRequest request = new DeleteRequest(indexName, id);
DeleteResponse response = esClient.delete(request, RequestOptions.DEFAULT);
if (response.status() == RestStatus.OK) {
log.info("删除成功");
}
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
修改文档
public void updateDoc() {
try {
String indexName = "test_index_create_2";
String id = "12";
Article article = new Article();
article.setTitle("java是世界上最好的语言-update");
article.setContent("程序员们放下手里的鼠标和键盘,抄起凳子打了起来-update");
UpdateRequest request = new UpdateRequest(indexName, id);
request.doc(JSON.toJSONString(article), XContentType.JSON);
UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);
log.info("response: " + JSON.toJSONString(response));
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
文档搜索
分页搜索
public void pageSearch() {
try {
String indexName = "test_index_create_2";
SearchRequest request = new SearchRequest(indexName);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.from(0); // 从第几条开始
builder.size(10); // 查几个
builder.sort("id", SortOrder.DESC); // 根据什么排序
builder.query(QueryBuilders.matchAllQuery()); // 查询全部
request.source(builder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
if (response.status() != RestStatus.OK) {
throw new Exception("搜索错误");
}
SearchHits hits = response.getHits();
log.info("数据总数:" + hits.getTotalHits());
log.info("搜索用时:" + response.getTook());
log.info("搜索结果:");
for (SearchHit hit : hits) {
log.info("字符串" + hit.getSourceAsString());
log.info("java对象:" + JSON.toJavaObject(JSON.parseObject(hit.getSourceAsString()), Article.class));
log.info("map对象" + hit.getSourceAsMap().toString());
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
简单搜索
public void simpleSearch() {
try {
SearchRequest request = new SearchRequest("test_index_create_2");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(10);
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "update");
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("content", "update");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(matchQueryBuilder).must(termQueryBuilder);
request.source(searchSourceBuilder.query(boolQueryBuilder));
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
printResp(response);
}catch (Exception e) {
log.error(e.getMessage(), e);
}
}
高亮搜索常用的条件构造器:
QueryBuilders.termQuery(“key”, obj) 完全匹配
QueryBuilders.termsQuery(“key”, obj1, obj2…) 一次匹配多个值
QueryBuilders.matchQuery(“key”, Obj) 单个匹配, field不支持通配符, 前缀具高级特性
QueryBuilders.multiMatchQuery(“text”, “field1”, “field2”…) 匹配多个字段, field有通配符忒行
QueryBuilders.matchAllQuery() 匹配所有文件复合条件构造器:
QueryBuilders.boolQuery()
.must(termQuery(“content”, “test1”)) 相当于 与 & =
.mustNot(termQuery(“content”, “test2”)) 相当于 非 ~ !=
.should(termQuery(“content”, “test3”)) 相当于 或 | or
.filter(termQuery(“content”, “test5”)); 过滤
public void highLightSearch() {
try {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "java");
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("");
highlightBuilder.postTags("");
highlightBuilder.fields().add(new HighlightBuilder.Field("title"));
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(matchQueryBuilder);
searchSourceBuilder.highlighter(highlightBuilder);
SearchRequest request = new SearchRequest("test_index_create_2");
request.source(searchSourceBuilder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
log.info(JSON.toJSONString(response));
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
Map highlightFields = hit.getHighlightFields();
HighlightField highlightField = highlightFields.get("title");
Text[] fragments = highlightField.getFragments();
for (Text fragment : fragments) {
log.info("高亮字段:" + fragment.toString());
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}



