ElasticSeach(六、springboot集成ES high level client)


這里之所以選擇high level client方式是因為transportClient在7.X版本中廢棄,預計會在8版本徹底刪除。

可參考官方文檔地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.6/java-rest-high-getting-started-maven.html

配置文件

pom.xml

這里有個小坑,在使用官方文檔的依賴包時,發現maven下載的es相關jar包竟然是6.4版本的,導致出現了很多問題。

通過 https://www.jianshu.com/p/acc8e86cc772 可解決jar包版本不一致的問題,再次感謝大佬分享學習的精神。

        <!-- es -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.6.1</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.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.6.1</version>
        </dependency>

 application.yml

es:
  host: 10.32.16.179 port: 9200 schema: http

索引管理

判斷索引是否存在

@Service
public class ElasticSearchServiceImpl implements ElasticSearchService { private static final Logger logger = LoggerFactory.getLogger(ElasticSearchServiceImpl.class); @Autowired private RestHighLevelClient restHighLevelClient; /** * 根據索引名稱判斷索引是否已存在 * @param indexName * @return * @throws IOException */ @Override public boolean isExistsIndex(String indexName) throws IOException { return restHighLevelClient.indices().exists(new GetIndexRequest(indexName), RequestOptions.DEFAULT); } }

創建索引

官方提供了三種創建mapping的方式,這里在后端寫死了mapping,如果需要索引管理,可通過前端傳入參數構建。

 /**
     * 創建索引
     * @param indexName
     * @throws IOException
     */
    @Override
    public void createIndex(String indexName) throws IOException { if(isExistsIndex(indexName)){ logger.error("indexName={} 已存在,無法創建", indexName); return; } CreateIndexRequest request = new CreateIndexRequest(indexName); //設置分片和備份  request.settings(Settings.builder() .put("index.number_of_shards",3) .put("index.number_of_replicas",2) .build()); //第一種,json字符串 request.mapping("{\n" + "\t\"properties\": {\n" + "\t\t\"username\": {\n" + "\t\t\t\"type\": \"text\"\n" + "\t\t},\n" + "\t\t\"city\": {\n" + "\t\t\t\"type\": \"keyword\"\n" + "\t\t}\n" + "\t}\n" + "}", XContentType.JSON); //第二種,Map // Map<String,Object> username = new HashMap<>(); // username.put("type","text"); // Map<String,Object> city = new HashMap<>(); // city.put("type","keyword"); // Map<String,Object> properties = new HashMap<>(); // properties.put("username",username); // properties.put("city",city); // Map<String,Object> mapping = new HashMap<>(); // mapping.put("properties",properties); // request.mapping(mapping); //第三種,XContentBuilder // XContentBuilder builder = XContentFactory.jsonBuilder(); // builder.startObject(); // { // builder.startObject("properties"); // { // builder.startObject("username"); // { // builder.field("type","text"); // } // builder.endObject(); // // builder.startObject("city"); // { // builder.field("type","keyword"); // } // builder.endObject(); // } // builder.endObject(); // } // builder.endObject(); //  restHighLevelClient.indices().create(request,RequestOptions.DEFAULT); }

刪除索引

/**
     * 刪除索引
     * @param indexName
     * @throws IOException
     */
    @Override
    public void deleteIndex(String indexName) throws IOException { if(!isExistsIndex(indexName)){ logger.error("indexName={} 索引不存在", indexName); return; } restHighLevelClient.indices().delete(new DeleteIndexRequest(indexName),RequestOptions.DEFAULT); }

文檔管理

新增或更新文檔

id為空則新增,不為空則更新

ElasticEntity

package com.wk.entity;

/**
 * 泛型,es入參實體類
 * @param <T>
 */
public class ElasticEntity<T> { private String id; private T data; public String getId() { return id; } public void setId(String id) { this.id = id; } public T getData() { return data; } public void setData(T data) { this.data = data; } }

EsTestEntity

package com.wk.entity;

/**
 * controller接收實體類
 */
public class EsTestEntity { private String id; private String username; private String city; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } }

業務類

官方新增文檔也有三種方式,和創建索引類似,這里不一一列舉了

/**
     * 新增或更新文檔
     * @param indexName
     * @param elasticEntity
     * @throws IOException
     */
    @Override
    public void insertOrUpdateDocument(String indexName, ElasticEntity elasticEntity) throws IOException { IndexRequest indexRequest = new IndexRequest(indexName); indexRequest.id(elasticEntity.getId()); indexRequest.source(JSONObject.toJSONString(elasticEntity.getData()),XContentType.JSON); restHighLevelClient.index(indexRequest,RequestOptions.DEFAULT); }

controller

還可在插入之前校驗一下index是否存在,這里省略了只簡單實現了demo

@PostMapping("insertOrUpdateDocument/{indexName}")
public Map<String,String> insertOrUpdateDocument(@PathVariable String indexName,@RequestBody EsTestEntity esTestEntity){
ElasticEntity<EsTestEntity> entity = new ElasticEntity<>();
//注冊生成UUID插入實體類的ID
if(StringUtils.isEmpty(esTestEntity.getId())){
String id = UUID.randomUUID().toString();
entity.setId(id);
esTestEntity.setId(id);
}
entity.setId(esTestEntity.getId());
entity.setData(esTestEntity);
try {
elasticSearchServiceImpl.insertOrUpdateDocument(indexName,entity);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

條件查詢

 controller

  @PostMapping("searchDocument/{indexName}")
    public List<EsTestEntity> searchDocument(@PathVariable String indexName, @RequestBody EsTestEntity esTestEntity){ try { SearchSourceBuilder builder = new SearchSourceBuilder(); Map<String,Object> requestMap = BeanUtil.convertToMap(esTestEntity); for(Map.Entry<String,Object> entry:requestMap.entrySet()){ builder.query(QueryBuilders.matchQuery(entry.getKey(),entry.getValue())); } //分頁 builder.from(0); builder.size(5); //排序 builder.sort("city", SortOrder.ASC); //設置超時時間 builder.timeout(new TimeValue(60, TimeUnit.SECONDS)); return elasticSearchServiceImpl.searchDocument(indexName,builder,EsTestEntity.class); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }

service

  /**
     * 條件查詢
     * @param indexName
     * @param builder
     * @param c
     * @param <T>
     * @return
     * @throws IOException
     */
    @Override
    public <T> List<T> searchDocument(String indexName, SearchSourceBuilder builder, Class<T> c) throws IOException { SearchRequest searchRequest = new SearchRequest(indexName); searchRequest.source(builder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); SearchHit[] searchHits = searchResponse.getHits().getHits(); List<T> res = new ArrayList<>(); for(SearchHit searchHit:searchHits){ res.add(JSONObject.parseObject(searchHit.getSourceAsString(),c)); } return res; }

高亮條件查詢

controller

    @PostMapping("searchHighlightDocument/{indexName}")
    public List<EsTestEntity> searchHighlightDocument(@PathVariable String indexName, @RequestBody EsTestEntity esTestEntity){ try { SearchSourceBuilder builder = new SearchSourceBuilder(); Map<String,Object> requestMap = BeanUtil.convertToMap(esTestEntity); for(Map.Entry<String,Object> entry:requestMap.entrySet()){ builder.query(QueryBuilders.matchQuery(entry.getKey(),entry.getValue())); } builder.from(0); builder.size(5); builder.sort("city", SortOrder.ASC); builder.timeout(new TimeValue(60, TimeUnit.SECONDS)); HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.preTags("<front color = 'red'>"); highlightBuilder.postTags("</front>"); HighlightBuilder.Field field = new HighlightBuilder.Field("username"); highlightBuilder.field(field); builder.highlighter(highlightBuilder); return elasticSearchServiceImpl.searchHighlightDocument(indexName,builder,EsTestEntity.class); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }

service

  /**
     * 高亮條件查詢
     * @param indexName
     * @param builder
     * @param c
     * @param <T>
     * @return
     * @throws IOException
     */
    @Override
    public <T> List<T> searchHighlightDocument(String indexName, SearchSourceBuilder builder, Class<T> c) throws IOException { SearchRequest searchRequest = new SearchRequest(indexName); searchRequest.source(builder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); SearchHit[] searchHits = searchResponse.getHits().getHits(); List<T> res = new ArrayList<>(); for(SearchHit searchHit:searchHits){ //返回結果轉換成Map Map<String,Object> sourceMap = searchHit.getSourceAsMap(); //獲取高亮的返回結果 Map<String, HighlightField> map = searchHit.getHighlightFields(); //循環設置的高亮字段 for(Map.Entry<String, HighlightField> entry:map.entrySet()){ //將高亮字段格式替換原結果中的值 sourceMap.put(entry.getKey(),entry.getValue().getFragments()[0].toString()); } res.add(JSONObject.parseObject(JSONObject.toJSONString(sourceMap),c)); } return res; }

返回結果:

刪除文檔

   /**
     * 根據ID刪除文檔
     * @param indexName
     * @param id
     * @throws IOException
     */
    @Override
    public void deleteDocumentById(String indexName, String id) throws IOException { DeleteRequest deleteRequest = new DeleteRequest(indexName,id); restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT); }

還有條件刪除等API,可以參考官方文檔,這里不一一列舉了

批量操作

批量新增

   /**
     * 批量新增
     * @param indexName
     * @param elasticEntities
     * @throws IOException
     */
    @Override
    public void insertDocumentBatch(String indexName, List<ElasticEntity> elasticEntities) throws IOException { BulkRequest bulkRequest = new BulkRequest(); elasticEntities.forEach(item ->{ bulkRequest.add(new IndexRequest(indexName).id(item.getId()).source(JSONObject.toJSONString(item.getData()),XContentType.JSON)); }); restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT); }

批量刪除

    /**
     * 批量刪除文檔
     * @param indexName
     * @param idList
     * @param <T>
     * @throws IOException
     */
    public <T> void deleteDocumentBatch(String indexName, Collection<T> idList) throws IOException {
        BulkRequest bulkRequest = new BulkRequest(); idList.forEach(item ->{ bulkRequest.add(new DeleteRequest(indexName, item.toString())); }); restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM