Elasticsearch 接口介紹和java API實例

說明

  • 本博客是繼上篇的擴展,整理介紹操作和官方java API功能,並創建實例java maven項目,記性實際操作。

http操作

接口說明

  • 官方接口語法curl ‐X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' ‐d '<BODY>'
參數 解釋
VERB 適當的HTTP方法即:GET、POST、PUT、HEAD、DELTETE
PROTOCOL http或https,當前官方爲http
HOST 任意節點的主機名,分佈式安裝也是任意節點
PORT http服務端口,默認9200
PATH API的終端路徑,如_count返回集羣中文檔數量
QUERY——STRING 任意可選的查詢字符串參數
BODY 一個JSON格式的請求體,非必須

創建索引庫並mapping

  • 請求put http://172.0.0.1:9200/hello 創建hello索引
  • 請求體:
    • article:type類型;相當於這個索引庫中有張表叫做article下面定義的這張表中的字段的定義,字段默認爲不索引的;
    • analyzer:分詞器使用標準分詞器
    {
        "mappings": {
            "article": {
                "properties": {
                    "id": {
                        "type": "long",
                        "store": true,
                        "index": "not_analyzed"
                    },
                    "title": {
                        "type": "text",
                        "store": true,
                        "index": "analyzed",
                        "analyzer": "standard"
                    },
                    "content": {
                        "type": "text",
                        "store": true,
                        "index": "analyzed",
                        "analyzer": "standard"
                    }
                }
            }
        }
    }
    

創建索引庫再mapping

  • 創建索引庫put http://172.0.0.1:9200/hello2
  • 添加mapping
    • 請求PUT http://127.0.0.1:9200/hello2/article/_mapping
    • 請求體:
    {
       "article": {
              "properties": {
                  "id": {
                      "type": "long",
                      "store": true,
                      "index": "not_analyzed"
                  },
                  "title": {
                      "type": "text",
                      "store": true,
                      "index": "analyzed",
                      "analyzer": "standard"
                  },
                  "content": {
                      "type": "text",
                      "store": true,
                      "index": "analyzed",
                      "analyzer": "standard"
                  }
              }
          }
    }
    

刪除索引

  • 請求DELETE http://127.0.0.1:9200/hello2

創建文檔

  • 請求POST http://127.0.0.1:9200/hello/article/1
  • 請求體,一般_id和id值相同
{
    "id": 1,
    "title": "ElasticSearch是一個基於Lucene的搜索服務器",
    "content": "它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並作爲Apache許可條款下的開放源碼發佈,是當前流行的企業級搜索引擎。設計用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。"
}

修改文檔

  • 請求POST http://127.0.0.1:9200/hello/article/1
  • 請求體
{
    "id": 1,
    "title": "第一次修改ElasticSearch是一個基於Lucene的搜索服務器",
    "content": "第一次修改它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並作爲Apache許可條款下的開放源碼發佈,是當前流行的企業級搜索引擎。設計用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。"
}

刪除文檔

  • 請求DELETE http://127.0.0.1:9200/hello/article/2

查看文檔

  • 查看文檔有三種方式
    • 根據id查看
      • 請求GET http://127.0.0.1:9200/hello/article/1
    • 更加關鍵詞查看
      • 請求POST http://127.0.0.1:9200/hello/article/_search
      • 請求體
      {
      "query": {
          "term": {
              "title": "搜"
          }
        }
      }
      
    • 更加輸入內容分詞再查看
      • 請求POST http://127.0.0.1:9200/hello/article/_search
      • 請求體
      {
      "query": {
          "query_string": {
              "default_field": "title",
              "query": "搜索服務器"
          }
        }
      }
      

官方java API文檔

  • 以下都是我從官方一個個閱讀整理的,全部基於RestHightLevelClient,TransportClient 8版本後刪除。

文檔詳情

java API代碼實現

查詢類說明

  • RangeQueryBuilder 範圍查找 gt:大於 lt:小於 gte:大於等於 lte:小於等於
  • WildcardQueryBuilder 模糊查詢 使用*表示任意字符
  • TermQueryBuilder 精確查詢
  • BoolQueryBuilder 布爾類型查詢 用於多條件的拼接(可用使用以下三個方法進行拼接條件)
  • must 必須的 文檔必須滿足匹配條件
  • must_not 文檔必須不匹配條件
  • should 或者 文檔只要滿足一個或多個條件

導包

<dependency>
  <groupId>org.elasticsearch</groupId>
  <artifactId>elasticsearch</artifactId>
  <version>7.3.0</version>
</dependency>

<dependency>
  <groupId>org.elasticsearch.client</groupId>
  <artifactId>elasticsearch-rest-high-level-client</artifactId>
  <version>7.3.0</version>
</dependency>

java工具類

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.http.HttpHost;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
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.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import lombok.extern.slf4j.Slf4j;


@Slf4j //使用了lombok,可以用手動引入private static final Logger log = LoggerFactory.getLogger(ESRestUtil.class);
public final class ESRestUtil {
	 
	    private RestHighLevelClient client;
	    
	    
	    public ESRestUtil() {
	        RestHighLevelClient client = new RestHighLevelClient(
	                RestClient.builder(
	                        //集羣節點
//	                        new HttpHost("localhost", 9200, "http"),
	                        new HttpHost("localhost", 9200, "http")));
	        this.client = client;
	    }
	    
	    /**
	     * 關閉連接
	     */
	    public void shutdown(){
	        if(client!=null){
	            try {
	                client.close();
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	    }
	    
	    /**
	     * 創建index
	     * @param index 創建index
	     * @param numberShared 分片數
	     * @param numberReplicas 備份數
	     * @return
	     */
	    public boolean createIndex(String index,int numberShared,int numberReplicas) {
	    	CreateIndexRequest request = new CreateIndexRequest(index);
	    	
	    	//設置分片和備份數
	    	request.settings(Settings.builder() 
	    		    .put("index.number_of_shards", numberShared)
	    		    .put("index.number_of_replicas", numberReplicas)
	    		);
	    	
	    	//索引別名
	    	request.alias(new Alias(index+"_alias").filter(QueryBuilders.termQuery("user", "kimchy"))); 
	    	
	    	try {
				 client.indices().create(request, RequestOptions.DEFAULT);
			} catch (IOException e) {
				log.error(e.toString(),e);
				return false;
			}
	    	return true;
	    	
	    }
	    
	    //TODO 創建索引和規則
	    
	    /**
	     * 添加數據和修改
	     * 文檔地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.10/java-rest-high-document-index.html
	     * @throws IOException
	     */
	    public boolean  addDataOrUpload(String index,String id,String jsonString)  {
	    	//指定索引
	    	IndexRequest request = new IndexRequest(index);
	    	//指定id
	    	request.id(id); 
	    	
	    	//添加的數據 文檔
	    	request.source(jsonString, XContentType.JSON);
	    	
	    	//同步執行
	    	IndexResponse indexResponse;
			try {
				indexResponse = client.index(request, RequestOptions.DEFAULT);
			} catch (IOException e) {
				log.error("添加數據失敗"+e.toString(),e);
				return false;
			}
	    	
	    	if(indexResponse.getResult()==DocWriteResponse.Result.CREATED) {
	    		log.info("First Create");
	    	}else if(indexResponse.getResult() ==DocWriteResponse.Result.UPDATED ) {
	    		log.info("Data Update");
	    	}
	    	
	    	return true;
	    	//異步添加
//	    	ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
//	    	    @Override
//	    	    public void onResponse(IndexResponse indexResponse) {
//	    	        
//	    	    }
//
//	    	    @Override
//	    	    public void onFailure(Exception e) {
//	    	        
//	    	    }
//	    	};
//	    	
//	    	client.indexAsync(request, RequestOptions.DEFAULT, listener);
	    }
	    
	 
	    /**
	     * 獲取指定index和id的 數據
	     * @param index
	     * @param id
	     * @return
	     */
	    public Map<String, Object> getStringById(String index,String id){
	    	log.info("Search Index:{}  And Id:{}",index,id);
	        GetRequest getRequest = new GetRequest(index,id);  //index 和id
	        GetResponse response = null;
	        try {
	            response = this.client.get(getRequest, RequestOptions.DEFAULT);
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	        
	        //按字段Key獲取對應的值
	        //DocumentField field = response.getField("content");
	        //獲取全部的map,除了正常的值之外,會存在key是@version和@timestamp的值
	        Map<String, Object> source =  response.getSource();
	        
	        log.info("Result Is:"+JsonUtil.toJson(source));
	       return source;
	    }
	 
	    /**
	     * 根據指定的內容,模糊查詢或精確查詢所有Doc。
	     * @param content
	     * @return
	     */
	    public List<Map<String,Object>> getArticle(String index,String key,String content){
//	        QueryBuilder qb= QueryBuilders.boolQuery().must(QueryBuilders.termQuery("title","JAVA開發工程師")).must(QueryBuilders.termQuery("age",30)) ;
//	        //精確查詢
	        QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(key, content);
//	        //模糊查詢
//	        QueryBuilder matchQueryBuilder = QueryBuilders.matchPhraseQuery("content", content);
	        
	        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//	        sourceBuilder.query(QueryBuilders.termQuery("content", content));
	        sourceBuilder.query(matchQueryBuilder);
	        sourceBuilder.from(0);
	        sourceBuilder.size(10);
	        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
	        
	        SearchRequest searchRequest = new SearchRequest();
	        searchRequest.indices(index);
	        searchRequest.source(sourceBuilder);
	        SearchResponse searchResponse;
	        List<Map<String,Object>> list = new ArrayList<>();
	
	        try {
	            searchResponse = this.client.search(searchRequest,RequestOptions.DEFAULT);
	            SearchHits searchHits =  searchResponse.getHits();
	            for(SearchHit hit:searchHits.getHits()){
	                System.out.println( hit.getSourceAsString());
	                list.add(hit.getSourceAsMap());
	            }
	        } catch (IOException e) {
	            e.printStackTrace();
	        }

	        return list;
	    }
	    
	    /**
	     * 模糊查詢
	     * @param index
	     * @param key
	     * @param value
	     * @return
	     */
	    public SearchHits search(String index,String key,String value){
	        QueryBuilder matchQueryBuilder = QueryBuilders.matchPhraseQuery(key, value);
	        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
	        
//	        sourceBuilder.query(QueryBuilders.termQuery("content", content));
	        sourceBuilder.query(matchQueryBuilder);
	        sourceBuilder.from(0);
	        sourceBuilder.size(100);
	        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
	        SearchRequest searchRequest = new SearchRequest();
	        searchRequest.indices(index);
	        searchRequest.source(sourceBuilder);
	        SearchResponse searchResponse;
	        List<Map<String,Object>> list = new ArrayList<>();
	        SearchHits searchHits = null;
	        try {
	            searchResponse = this.client.search(searchRequest,RequestOptions.DEFAULT);
	            searchHits =  searchResponse.getHits();
	            for(SearchHit hit:searchHits.getHits()){
	                System.out.println( hit.getSourceAsString());
	                list.add(hit.getSourceAsMap());
	            }
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	        return searchHits;
	    }
	 
	    /**
	     * 刪除數據
	     * @param titleName
	     * @return
	     */
	    public long deleteArticle(String titleName){
	        long deleteNum = 0l;
	 
	        SearchHits searchHits = search("article-2019.08.08.03","title",titleName);
	        System.out.println("Exxcute Start" );
	        deleteCommon(searchHits);
	        //deleteAsync(searchHits);
	        System.out.println("Exxcute Done" );
	        return deleteNum;
	 
	    }
	 
	    /**
	     * 刪除數據
	     * @param index
	     * @param id
	     */
	    public boolean deleteData(String index,String id) {
	    	DeleteRequest deleteRequest= new DeleteRequest(index,id);
	    	try {
                DeleteResponse deleteResponse = this.client.delete(deleteRequest,RequestOptions.DEFAULT);
                System.out.println("Delete Done【"+deleteResponse.getId()+"】,Status:【" + deleteResponse.status() + "】");
                return true;
            } catch (IOException e) {
            	log.error(e.toString(),e);
            }
	    	return false;
	    	
	    }
	    
	    /**
	     * 正常刪除
	     * @param searchHits
	     */
	    private void deleteCommon (SearchHits searchHits){
	        DeleteRequest deleteRequest = new DeleteRequest();
	        for(SearchHit hit:searchHits.getHits()) {
	            deleteRequest = new DeleteRequest("article-2019.08.08.03",hit.getId());
	            try {
	                DeleteResponse deleteResponse = this.client.delete(deleteRequest,RequestOptions.DEFAULT);
	                System.out.println("Delete Done【"+deleteResponse.getId()+"】,Status:【" + deleteResponse.status() + "】");
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	    }
	 
	    /**
	     * 異步刪除
	     * @param searchHits
	     */
	    @SuppressWarnings("unused")
		private void deleteAsync (SearchHits searchHits) {
	        DeleteRequest deleteRequest = new DeleteRequest();
	        for(SearchHit hit:searchHits.getHits()){
	            deleteRequest = new DeleteRequest("article-2019.08.08.03",hit.getId());
	 
	 
	            //異步刪除
	            this.client.deleteAsync(deleteRequest, RequestOptions.DEFAULT, new ActionListener<DeleteResponse>() {
	                @Override
	                public void onResponse(DeleteResponse deleteResponse) {
	                    RestStatus restStatus = deleteResponse.status();
	                    int status = restStatus.getStatus();
	                    deleteResponse.getId();
	                    System.out.println("Delete Done【"+deleteResponse.getId()+"】,Status:【" + status + "】");
	                }
	                @Override
	                public void onFailure(Exception e) {
	                    e.printStackTrace();
	                    System.out.println("ERROR  " + hit.getId());
	                }
	            });
	        }
	 
	    }

}

總結

  • 官方java文檔中,所有API都有兩種形式,同步和異步,系統執行效率要求高的可考慮異步接口,同樣業務流程隨之增大。
  • 說點廢話,有用共勉,無用忽略。
    • 程序員個人成長,第一步掌握一門編程語言,掌握的標準是,能用該語言完成任何需求,不考慮執行效率。第二步,實現基礎上優化代碼,大幅提升效率。第三步,考慮功能分析和架構、功能設計,評估不同編程語言的特性和技術可控性、擴展性,能爲項目搭建和開發提供有效的技術架構和流程方案。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章