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();