1. 程式人生 > >ElasticSearch5.6.8(四)資料操作

ElasticSearch5.6.8(四)資料操作

使用JAVA來操作Elasticsearch,我的環境為
jdk1.8
ES5.6.8
transport 5.6.8

環境準備

開發需要的jar包

使用maven管理jar包,如果沒有安裝x-pack外掛,只引入上第一個依賴就夠

 <!-- ealsticsearch -->
    <dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>transport</artifactId>
      <version
>
5.6.8</version> </dependency> <!-- 安裝x-pack外掛後 --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>x-pack-transport</artifactId> <version>5.6.8</version> </dependency>

JAVA API

建立一個連線

使用封裝的方式寫一個工具類用於獲取操作客戶端,類似於jdbc中先寫一個獲取connection的方法。

無x-pack方式

/**
    * 獲取操作連線
    * @return
    */
   public static TransportClient getTransportClient() {

       // 叢集設定
       Settings settings = Settings.builder()
               .put("cluster.name", "elasticsearch")//叢集名稱
               .build();
       TransportClient client = new
PreBuiltTransportClient(settings); //新增叢集地址和tcp服務埠 IP是由叢集的各個node的ip組成的陣列 try { for (String ip : IP) { client.addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName(ip), 9300)); } } catch (UnknownHostException e) { e.printStackTrace(); } return client; }

安裝了x-pack後

這裡在貼一下安裝了x-pack後使用的初始化方法

public static TransportClient getTransportClient() {
     //安裝x-pack後的初始化方法
     Settings settings = Settings.builder()
             .put("cluster.name", clusterName) //叢集名
             .put("client.transport.sniff", true) 
             .put("xpack.security.transport.ssl.enabled", false)
             .put("xpack.security.user", "elastic:changme")//x-pack使用者密碼
             .build();
      //使用的實現類與前面不同     
     TransportClient client = new PreBuiltXPackTransportClient(settings);
     // 一定要注意,9300為elasticsearch的tcp埠
        try {
            for (String ip : IP) {
                client.addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName(ip), PORT));
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return client;
    }

增加索引和文件資料

建立索引的對映

使用JAVA API建立一個帶對映的索引,以通過它的field方法類設定

    TransportClient transportClient = getTransportClient(); 
    CreateIndexRequestBuilder createIndex=transportClient.admin().indices().prepareCreate(index);
        XContentBuilder mapping = XContentFactory.jsonBuilder()
                .startObject()
                .startObject("properties") //設定之定義欄位
                .startObject("name").field("type","text").field("analyzed","standard").endObject() //設定分析器
                .startObject("age").field("type","long").endObject()
                .startObject("class_name").field("type","keyword").endObject()
                .startObject("birth").field("type","date").field("format","yyyy-MM-dd").endObject()//設定Date的格式
                .endObject()
                .endObject();
        createIndex.addMapping(type, mapping);
        CreateIndexResponse res=createIndex.execute().actionGet();

插入文件

構建一個request,它有很多型別,建立索引使用IndexRequestBuilder 。
可以不設定id,es可以自動生成_id.
source的型別有很多,可以使用XContentFactory建立XContentBuilder,也可以使用json格式的字串 ,也可以使用Map來當資料來源。

    TransportClient client= ElasticSearchTestConfig.getTransportClient();
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("name","張三");
    map.put("age",22);
    IndexRequestBuilder create = clien.prepareIndex("my","text")
                .setSource(map);
    IndexResponse response = create.execute().actionGet();
  TransportClient client = ElasticSearchTestConfig.getTransportClient();
        IndexRequestBuilder create = clien.prepareIndex("my","text")
                .setSource(("{\"name\":\"張三\",\"age\":21 }",XContentType.JSON);
        IndexResponse response = create.execute().actionGet();

批量插入資料

使用BulkRequestBuilder 完成批量插入,雖然能完成批量操作,但一次也不要新增太多。因為request的大小有限制,具體的量與需要插入的資料大小有關。

BulkRequestBuilder bulkRequest = transportClient.prepareBulk();
for(Map source:sources){
   //新增請求
   bulkRequest.add(transportClient.prepareIndex(index,type)
           .setSource(source));
   }
  BulkResponse bulkResponse = bulkRequest.execute().actionGet();
}

刪除索引和文件資料

刪除索引

刪除建立的是DeleteIndexRequestBuilder

//先判斷下索引是否存在
 IndicesExistsRequest inExistsRequest = new IndicesExistsRequest(index);
 IndicesExistsResponse inExistsResponse = client.admin().indices()
                .exists(inExistsRequest).actionGet();
  //存在即進行刪除操作
 if(inExistsResponse.isExists()){
      DeleteIndexRequestBuilder delete = client.admin().indices().prepareDelete(index);
      DeleteIndexResponse dResponse = delete.execute().actionGet();   
 }

根據id刪除資料

DeleteRequestBuilder delete = client.prepareDelete("my","text","1");
        DeleteResponse response = delete.execute().actionGet();

根據搜尋返回值刪除資料

其中Query是一種QueryBuilder

DeleteByQueryAction.INSTANCE.newRequestBuilder(client).filter(Query).execute();

檢視資料、聚合資料、高亮結果

搜尋Query

一個搜尋使用下面的方式構建使用。面對不同的需求使用不同的QueryBuilder。

 TransportClient client = ElasticSearchTestConfig.getTransportClient();
 //構建一個query 即查詢條件
 QueryBuilder match = QueryBuilders.matchQuery("field","text");
 //根據查詢條件構建一個查詢問句
 SearchRequestBuilder search = client.prepareSearch("index")
                .setQuery(match)
                .setTypes("typeName")  //指定型別 可選
                .setFrom(0).setSize(10) //分頁 可選
                .addSort("title", SortOrder.DESC);//排序 可選
 //搜尋返回搜尋結果
 SearchResponse response = search.get(); 
 //命中的文件 
 SearchHits hits = response.getHits();
 //命中總數
 Long total = hits.getTotalHits()
 //迴圈檢視命中值
 for(SearchHit hit:hits.getHits()){
     //文件元資料
      String index = hit.getIndex();
      //文件的_source的值
      Map<String, Object> sourceMap = hit.getSourceAsMap();
 }      

搜尋全部

QueryBuilder matchAll = QueryBuilders.matchAllQuery();

欄位值包含搜尋

QueryBuilder match = QueryBuilders.matchQuery("field","text");

欄位值精確值匹配

QueryBuilder term = QueryBuilders.termQuery("field","text");
QueryBuilder terms = QueryBuilders.termsQuery("field","text","text2","text3");

字首搜尋

QueryBuilder prefix= QueryBuilders.prefixQuery("field","text");

模糊值搜尋

FuzzyQueryBuilder fuzzy= QueryBuilders.fuzzyQuery(field, value);

萬用字元搜尋

QueryBuilder wildcard= QueryBuilders.wildcardQuery(field,patten);

搜尋語句搜尋

QueryBuilder queryString= QueryBuilders.queryStringQuery("queryString");

多條件搜尋

搜尋需求:
重要性比較高:標題包含Elasticsearch或JAVA
內容同時包含Elasticsearch和JAVA

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.should(QueryBuilders.matchQuery("main_body","Elasticsearch JAVA")
                       .operator(Operator.AND).boost(1))
         .should(QueryBuilders.matchQuery("title","Elasticsearch JAVA"))
                        .operator(Operator.OR).boost(10)
               );

聚合搜尋Aggregation

聚合相當於SQL中的group,使用不同的AggregationBuilder能完成不同的聚合操作,這裡列舉幾種聚合。
語法如下:

TransportClient client = ElasticSearchTestConfig.getTransportClient();
//需要給聚合內容一個別名
AggregationBuilder aggregation = AggregationBuilders
    .terms("alias").field("field");
QueryBuilder allQuery = QueryBuilders.matchAllQuery();
SearchResponse response = client.prepareSearch("index")
     .setQuery(allQuery).addAggregation(aggregation).get();
//根據別名獲取聚合物件,不同聚合會返回不同的聚合物件
Terms terms = response.getAggregations().get("alias");
for(Terms.Bucket entry:terms.getBuckets()){
    //聚合的屬性值
    String value = entry.getKey().toString();
    //聚合後的數量
    long count = entry.getDocCount();
}

聚合某欄位

AggregationBuilder aggregation = AggregationBuilders
    .terms("alias").field("field");

統計某欄位的總數

ValueCountBuilder vcb=  AggregationBuilders.count("alias").field("field");

去重統計某欄位的總數

CardinalityBuilder aggregation = AggregationBuilders.cardinality("alias").field("field");  

聚合時間

可選擇不同的時間聚合方式

AggregationBuilder aggregation = AggregationBuilders
    .dateHistogram(alias).field(field)
    .format("yyyy-MM-dd")
    .dateHistogramInterval(DateHistogramInterval.DAY);

搜尋高亮

搜尋結果高亮顯示,使用方法如下

TransportClient client = ElasticSearchTestConfig.getTransportClient();
QueryBuilder query = QueryBuilders.matchQuery("title","JAVA");

//建立高亮配置
HighlightBuilder hiBuilder=new HighlightBuilder();
//配置高亮作用欄位
hiBuilder.field("title");
//可以設定返回高亮詞周圍多少字元,以及返回幾個段
hiBuilder.field("main_body",100,1);
//在高亮詞前新增標籤
hiBuilder.preTags("<em style='color:red'>");
//高亮詞的後標籤
hiBuilder.postTags("</em>");

SearchResponse response = client.prepareSearch("index")
    .setQuery(query).highlighter(hiBuilder).get();
//迴圈命中
for(SearchHit hit:response.getHits().getHits()){
      //比如配置了兩個欄位都高亮,key是欄位名,value就是加了高亮的值
      Map<String, HighlightField> highlightFieldMap = hit.getHighlightFields();
      HighlightField highlightField = highlightFieldMap.get("title");
      if(highlightField!=null){
           //獲取高亮的所有段
           Text[] fragments = highlightField.getFragments();
           for(Text text:fragments){
                System.out.println("text的值是:"+text);
           }
       }
}

修改已有資料

修改操作使用UpdateRequestBuilder構建一個修改請求,然後使用setDoc方法傳入新的值即可,這裡採用的不是覆蓋而是更新存在值,新增不存在屬性的操作

 UpdateResponse response = client.prepareUpdate("my","test","1")
                .setDoc(source).get();