# 建立索引
# "dynamic": "strict"====》不允許動態新增欄位,如果遇到新的欄位,就丟擲異常。
# "dynamic": "true"===》允許動態新增新的欄位。這是預設值
# "dynamic": "false"===》忽略新的欄位。在原有的對映基礎上,當有新的欄位時,不會主動的新增新的對映關係,只作為查詢結果出現在查詢中。
PUT my_blogs
{
"mappings": {
"dynamic": "strict",
"properties": {
"author": {
"type": "keyword"
},
"title": {
"type": "keyword"
},
"content": {
"type": "text"
},
"views": {
"type": "integer"
},
"created": {
"type": "date",
"format":"yyyy-MM-dd HH:mm:ss"
}
}
}
}
keyword與text的區別:text會被分詞;
date型別的預設格式為:”strict_date_optional_time||epoch_millis”,文件
GET my_blogs/_mapping
DELETE /test_blogs
# 指定文件id為blog1,如果未指定則會自動生成
# 新增
POST my_blogs/_doc/blog1
{
"author": "lzc",
"title":"Learning ElasticSearch",
"content":"學習ElasticSearch技術",
"views": 0,
"created": "2020-05-06 08:44:00"
}
POST my_blogs/_doc/blog2
{
"author": "lzc",
"title":"Learning Java",
"content":"學習java技術",
"views": 0,
"created": "2020-05-06 08:44:00"
}
POST my_blogs/_doc/
{
"author": "lzc",
"title":"Learning RocketMQ",
"content":"學習RocketMQ技術",
"views": 0,
"created": "2020-05-06 08:56:00"
}
# 查詢所有
GET /my_blogs/_search
{
"query": {
"match_all": {}
}
}
term、terms
term查詢、terms查詢會去倒排索引中尋找確切的term,它並不知道分詞器的存在,這種查詢適合keyword、numeric、date等明確值的。
# term查詢:查詢 author 欄位裡有某個關鍵詞的文件
GET /my_blogs/_search
{
"query": {
"term": {
"author": "lzc"
}
}
}
# terms 查詢:查詢 author 欄位裡有多個關鍵詞的文件
GET /my_blogs/_search
{
"query": {
"terms": {
"author": [
"zhangsan",
"lzc"
]
}
}
}
match、multi_match
match查詢知道分詞器的存在,會對field進行分詞操作,然後再查詢
# 它和term區別可以理解為term是精確查詢,match是模糊查詢;
# match會對"學習RocketMQ"分詞,分詞規則跟分詞器有關,可能會被分為"學習"與"RocketMQ"
# term 可以認為這是一個單詞
GET /my_blogs/_search
{
"query": {
"match": {
"content": "學習RocketMQ"
}
}
}
# 查詢多個欄位
GET /my_blogs/_search
{
"query": {
"multi_match": {
"query": "RocketMQ",
"fields": ["content","xxxx"]
}
}
}
_source
指定需要返回的欄位
# 只返回author、title欄位
GET /my_blogs/_search
{
"_source": ["author","title"],
"query": {
"match_all": {}
}
}
Bool查詢
must
返回的文件必須滿足must子句的條件,並且參與計算分值。
# term查詢:查詢 author 欄位裡有某個關鍵詞的文件
GET /my_blogs/_search
{
"query": {
"bool": {
"must": [
{"term":{"author":"lzc"}}
]
}
}
}
# 匹配多個欄位
GET /my_blogs/_search
{
"query": {
"bool": {
"must": [
{"term":{"title":"java"}},
{"term":{"author":"zhangsan"}}
]
}
}
}
# terms 查詢:查詢某個欄位裡有多個關鍵詞的文件
GET /my_blogs/_search
{
"query": {
"bool": {
"must": [
{"terms":{"author":["lzc","zhangsan"]}}
]
}
}
}
must_not
返回的文件必須不滿足must_not定義的條件。
GET /my_blogs/_search
{
"query": {
"bool": {
"must_not": [
{"term":{"author":"zhangsan"}}
]
}
}
}
should
返回的文件可能滿足should子句的條件。在一個Bool查詢中,如果沒有must或者filter,有一個或者多個should子句,那麼只要滿足一個就可以返回。minimum_should_match
引數定義了至少滿足幾個子句。
# 相當於or語句
GET /my_blogs/_search
{
"query": {
"bool": {
"should": [
{"term":{"author":"lzc"}},
{"term":{"author":"zhangsan"}}
]
}
}
}
filter
返回的文件必須滿足filter子句的條件。但是不會像Must一樣,參與計算分值。
# 類似於and語句
GET /my_blogs/_search
{
"query": {
"bool": {
"filter": [
{"term":{"title":"java"}},
{"term":{"author":"zhangsan"}}
]
}
}
}
exists
# 查詢欄位為author的值不為null或者不為[]
GET /my_blogs/_search
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "author"
}
}
]
}
}
}
高亮查詢
單欄位查詢
GET /my_blogs/_search
{
"query": {
"match": {
"content": "RocketMQ"
}
},
"highlight": {
"pre_tags": [
"<tag1>"
],
"post_tags": [
"</tag1>"
],
"fields": {
"content": {}
}
}
}
查詢結果:
{
"_index" : "my_blogs",
"_type" : "_doc",
"_id" : "Bfh853EBC1bB8l9gL99x",
"_score" : 1.092264,
"_source" : {
"author" : "lzc",
"title" : "Learning RocketMQ",
"content" : "學習RocketMQ技術",
"views" : 0,
"created" : "2020-05-06 08:56:00"
},
"highlight" : {
"content" : [
"學習<tag1>RocketMQ</tag1>技術"
]
}
}
多欄位查詢
GET /my_blogs/_search
{
"query" : {
"multi_match": {
"query": "RocketMQ" ,
"fields" : [ "content", "title" ]
}
},
"highlight" : {
"pre_tags" : ["<tag1>"],
"post_tags" : ["</tag1>"],
"fields" : {
"title": {},
"content" : {}
}
}
}
# 透過id刪除
DELETE my_blogs/_doc/blog9
# 透過條件刪除
POST my_blogs/_delete_by_query
{
"query": {
"bool": {
"must": [
{
"term": {
"author": {
"value": "zhangsan"
}
}
}
]
}
}
}
# 根據id修改
POST my_blogs/_update/blog1
{
"doc": {
"author":"lizc"
}
}
# doc_as_upsert 設定 true, 如果id不存在就新增
POST my_blogs/_update/blog2
{
"doc": {
"author":"lizhencheng",
"title":"好好學習"
},
"doc_as_upsert" : true
}
ElasticSerch 的連線查詢有兩種方式實現
- nested
- parent和child關聯查詢
nested
建立索引
# 假設用來儲存部落格與部落格評論
PUT my_blogs
{
"mappings": {
"properties": {
"author": {
"type": "keyword"
},
"title": {
"type": "keyword"
},
"content": {
"type": "text"
},
"views": {
"type": "integer"
},
"created": {
"type": "date",
"format":"yyyy-MM-dd HH:mm:ss"
},
"comment": {
"type": "nested",
"properties": {
"commentName":{
"type":"keyword"
},
"commentContent":{
"type":"keyword"
},
"commentCreated":{
"type": "date",
"format":"yyyy-MM-dd HH:mm:ss"
}
}
}
}
}
}
新增資料
POST my_blogs/_doc/blog1
{
"author": "lzc",
"title":"Learning ElasticSearch",
"content":"學習ElasticSearch技術",
"views": 0,
"created": "2020-05-06 08:00:00",
"comment":[
{
"commentName":"zhangsan",
"commentContent":"commentContent1",
"commentCreated":"2020-05-07 08:00:00"
},
{
"commentName":"lisi",
"commentContent":"commentContent2",
"commentCreated":"2020-05-07 10:00:00"
},
{
"commentName":"wangwu",
"commentContent":"commentContent3",
"commentCreated":"2020-05-08 08:00:00"
}
]
}
POST my_blogs/_doc/blog2
{
"author": "xiaoli",
"title":"Learning Java",
"content":"學習Java技術",
"views": 0,
"created": "2020-05-07 08:00:00",
"comment":[
{
"commentName":"zhangsan",
"commentContent":"commentContent4",
"commentCreated":"2020-05-08 08:00:00"
}
]
}
查詢
# 查詢 author = lzc 並且 commentName = zhangsan
GET /my_blogs/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"author": {
"value": "lzc"
}
}
},
{
"nested": {
"path": "comment",
"query": {
"bool": {
"must": [
{
"term": {
"comment.commentName": {
"value": "zhangsan"
}
}
}
]
}
}
}
}
]
}
}
}
parent-child
建立索引
PUT my_blogs
{
"mappings": {
"properties": {
"blog_comment_relation": {
"type": "join",
"relations": {
"blog": [
"comment"
]
}
},
"author": {
"type": "keyword"
},
"title": {
"type": "keyword"
},
"content": {
"type": "text"
},
"views": {
"type": "integer"
},
"created": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"commentName": {
"type": "keyword"
},
"commentContent": {
"type": "keyword"
},
"commentCreated": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
}
新增資料
# 新增父節點
POST my_blogs/_doc/blog1
{
"author": "lzc",
"title":"Learning ElasticSearch",
"content":"學習ElasticSearch技術",
"views": 0,
"created": "2020-05-06 08:55:00",
"blog_comment_relation": {
"name":"blog"
}
}
POST my_blogs/_doc/blog2
{
"author": "zhangsan",
"title":"Learning Java",
"content":"學習java技術",
"views": 0,
"created": "2020-05-06 08:58:00",
"blog_comment_relation": {
"name":"blog"
}
}
# 新增子節點記錄
# 需要指定routing為父節點的id,使得他們處於同一個分片。無論是子節點還是孫子節點,routing都是指向父節點id
# parent 指定父元素id
PUT my_blogs/_doc/comment1?routing=blog1
{
"commentUserName": "lili",
"commentContent": "I am learning ElasticSearch",
"commentCreated":"2020-05-07 08:00:00",
"blog_comment_relation": {
"name": "comment",
"parent": "blog1"
}
}
PUT my_blogs/_doc/comment2?routing=blog1
{
"commentUserName": "jack",
"commentContent": "I am learning Java",
"commentCreated":"2020-05-07 09:00:00",
"blog_comment_relation": {
"name": "comment",
"parent": "blog1"
}
}
PUT my_blogs/_doc/comment3?routing=blog2
{
"commentUserName": "jackma",
"commentContent": "so easy",
"commentCreated":"2020-05-08 09:00:00",
"blog_comment_relation": {
"name": "comment",
"parent": "blog2"
}
}
查詢
# Has Child查詢,返回父文件
# "inner_hits": {} ==> 加了這個會將子文件一起查詢出來, 預設只會返回三條資料
# "inner_hits"裡面有四個屬性
# from: 返回結果的偏移量, 如"from": 2 ==> 從索引為2的位置返回size條資料
# size: inner_hits返回的最大數量。預設值為3。
# size: inner_hits => 預設情況最大可設定為100,可透過index.max_inner_result_window來設定
# sort: 如何對內部命中進行排序,如 "sort": [{"commentCreated":"desc"}]
# name: 用於響應中特定內部命中定義的名稱
GET /my_blogs/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"_id": {
"value": "blog1"
}
}
},
{
"has_child": {
"type": "comment",
"query": {
"bool": {
"must": [
{
"match_all": {}
}
]
}
},
"inner_hits": {
"size": 10,
"sort": [{"commentCreated":"desc"}]
}
}
}
]
}
}
}
# Has Parent查詢,返回子文件
# "inner_hits": {} ==> 加了這個會將父文件一起查詢出來
POST /my_blogs/_search
{
"query": {
"bool": {
"must": [
{
"has_parent": {
"parent_type": "blog",
"query": {
"match": {
"_id": "blog1"
}
},
"inner_hits": {}
}
}
]
}
}
}
比較
nested | parent/child | |
---|---|---|
優點 | 讀取效能高 | 父子文件可以獨立更新 |
缺點 | 每次更新需要更新整個文件 | 關聯關係,需要額外的記憶體,查詢效率相對較差 |
場景 | 頻繁查詢 | 頻繁更新 |
# size為0則不會返回文件資訊,只會返回聚合資訊
GET /my_blogs/_search
{
"size" : 0,
"aggs" : {
"author_blog_counts" : {
"terms" : {
"field" : "author"
}
}
}
}
返回結果
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"author_blog_counts" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "lzc",
"doc_count" : 2
},
{
"key" : "zhangsan",
"doc_count" : 1
}
]
}
}
}
將文件從一個索引複製到另一個索引。
# 將my_blogs中的資料複製到my_blogs_copy
POST _reindex
{
"source": {
"index": "my_blogs"
},
"dest": {
"index": "my_blogs_copy"
}
}
# 設定數量, 預設情況, size為1000
POST _reindex
{
"size": 1,
"source": {
"index": "my_blogs"
},
"dest": {
"index": "my_blogs_copy"
}
}
# 根據條件進行復制
POST _reindex
{
"size": 1000,
"source": {
"index": "my_blogs",
"query": {
"bool": {
"must": [
{
"term": {
"author": {
"value": "lzc"
}
}
}
]
}
}
},
"dest": {
"index": "my_blogs_copy"
}
}
www.elastic.co/guide/en/elasticsea...
scroll
www.elastic.co/guide/en/elasticsea...
www.elastic.co/guide/en/elasticsea...
配置
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.1.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.1.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.1.1</version>
</dependency>
與SpringBoot進行整合
elasticsearch.ip=localhost:9200
配置類
@Configuration
public class ESConfig {
/**
* 超時時間設為5分鐘
*/
private static final int TIME_OUT = 5 * 60 * 1000;
private static final int ADDRESS_LENGTH = 2;
private static final String HTTP_SCHEME = "http";
@Value("${elasticsearch.ip}")
String[] ipAddress;
@Bean
public RestClientBuilder restClientBuilder() {
HttpHost[] hosts = Arrays.stream(ipAddress)
.map(this::makeHttpHost)
.filter(Objects::nonNull)
.toArray(HttpHost[]::new);
return RestClient.builder(hosts);
}
@Bean(name = "restHighLevelClient")
public RestHighLevelClient highLevelClient(@Autowired RestClientBuilder restClientBuilder) {
restClientBuilder.setRequestConfigCallback(
new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(
RequestConfig.Builder requestConfigBuilder) {
return requestConfigBuilder.setSocketTimeout(TIME_OUT);
}
});
return new RestHighLevelClient(restClientBuilder);
}
private HttpHost makeHttpHost(String s) {
assert !StringUtils.isEmpty(s);
String[] address = s.split(":");
if (address.length == ADDRESS_LENGTH) {
String ip = address[0];
int port = Integer.parseInt(address[1]);
System.err.println(ip + "+" + port);
return new HttpHost(ip, port, HTTP_SCHEME);
} else {
return null;
}
}
}
建立索引
PUT my_blogs
{
"mappings": {
"properties": {
"blog_comment_relation": {
"type": "join",
"relations": {
"blog": [
"comment"
]
}
},
"author": {
"type": "keyword"
},
"title": {
"type": "keyword"
},
"content": {
"type": "text"
},
"views": {
"type": "integer"
},
"created": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"commentName": {
"type": "keyword"
},
"commentContent": {
"type": "keyword"
},
"commentCreated": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
}
編寫程式碼
官方文件:www.elastic.co/guide/en/elasticsea...
新增
www.elastic.co/guide/en/elasticsea...
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void insert() throws IOException {
Map<String, Object> blog = new HashMap();
blog.put("author","lzc");
blog.put("title","Learning ElasticSearch12");
blog.put("content","學習ElasticSearch技術");
Map<String, Object> blogCommentRelation1 = new HashMap();
blogCommentRelation1.put("name","blog");
blog.put("blog_comment_relation",blogCommentRelation1);
IndexResponse indexResponse1 = insert("my_blogs", "blog1", null, blog);
Map<String, Object> comment1 = new HashMap();
comment1.put("commentName","commentName1");
comment1.put("commentContent","commentContent1");
Map<String, Object> blogCommentRelation2 = new HashMap();
blogCommentRelation2.put("name","comment");
blogCommentRelation2.put("parent","blog1");
comment1.put("blog_comment_relation",blogCommentRelation2);
IndexResponse indexResponse2 = insert("my_blogs", "comment1", "blog1", comment1);
Map<String, Object> comment2 = new HashMap();
comment2.put("commentName","commentName2");
comment2.put("commentContent","commentContent2");
Map<String, Object> blogCommentRelation3 = new HashMap();
blogCommentRelation3.put("name","comment");
blogCommentRelation3.put("parent","blog1");
comment1.put("blog_comment_relation",blogCommentRelation2);
IndexResponse indexResponse3 = insert("my_blogs", "comment2", "blog1", comment2);
}
/**
* @param index 索引名
* @param id 主鍵id, 如果傳入null則會自動生成
* @param routing
* @param doc 文件內容
*/
public IndexResponse insert(String index, String id, String routing, Map<String, Object> doc) throws IOException {
IndexRequest indexRequest = new IndexRequest(index).source(doc);
if (id != null) {
indexRequest = indexRequest.id(id);
}
if (routing != null) {
indexRequest = indexRequest.routing(routing);
}
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
return indexResponse;
}
新增or修改
www.elastic.co/guide/en/elasticsea...
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void updateOrInsert() throws IOException {
Map<String, Object> blog = new HashMap();
blog.put("author","lzc");
blog.put("title","Learning ElasticSearch");
blog.put("content","學習ElasticSearch技術");
Map<String, Object> blogCommentRelation1 = new HashMap();
blogCommentRelation1.put("name","blog");
blog.put("blog_comment_relation",blogCommentRelation1);
UpdateResponse updateResponse = updateOrInsert("my_blogs", "blog2", null, blog);
Map<String, Object> comment = new HashMap();
comment.put("commentName","commentName3");
comment.put("commentContent","commentContent3");
Map<String, Object> blogCommentRelation2 = new HashMap();
blogCommentRelation2.put("name","comment");
blogCommentRelation2.put("parent","blog2");
comment.put("blog_comment_relation",blogCommentRelation2);
IndexResponse indexResponse2 = insert("my_blogs", "comment2", "blog2", comment);
}
/**
* 新增或修改
* @param index 文件索引
* @param id 文件id
* @param routing
* @param doc 文件欄位
*/
public UpdateResponse updateOrInsert(String index, String id, String routing, Map<String, Object> doc) throws IOException {
UpdateRequest request = new UpdateRequest(index,id);
if (routing != null) {
request = request.routing(routing);
}
request.doc(doc).docAsUpsert(true).retryOnConflict(5);
return restHighLevelClient.update(request, RequestOptions.DEFAULT);
}
透過id查詢
www.elastic.co/guide/en/elasticsea...
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void getDocumentById() throws IOException {
Map<String, Object> blogMap = getDocumentById("my_blogs", "comment1");
}
/**
* @param index 索引名
* @param id 文件id
*/
public Map<String, Object> getDocumentById(String index, String id) throws IOException {
GetRequest getRequest = new GetRequest(index, id);
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
if (getResponse.isExists()) {
return getResponse.getSourceAsMap();
}
return null;
}
透過id刪除
www.elastic.co/guide/en/elasticsea...
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void deleteDocumentById() throws IOException {
deleteDocumentById("my_blogs", "comment1");
}
/**
* @param index 索引名
* @param id 文件id
*/
public DeleteResponse deleteDocumentById(String index, String id) throws IOException {
DeleteRequest deleteRequest = new DeleteRequest(index, id);
DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
return deleteResponse;
}
條件查詢
www.elastic.co/guide/en/elasticsea...
@Test
public void searchRequest() throws IOException {
SearchRequest searchRequest = new SearchRequest("my_blogs");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery(); // 構造查詢條件
searchSourceBuilder.query(queryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println();
}
QueryBuilders.matchAllQuery()
相當於如下查詢
GET /my_blogs/_search
{
"query": {
"match_all": {}
}
}
term查詢
// 構造查詢條件
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
// 構造term
queryBuilder.must(QueryBuilders.termQuery("title", "Learning ElasticSearch"));
相當於如下查詢
GET /my_blogs/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"title": {
"value": "Learning ElasticSearch"
}
}
}
]
}
}
}
has_child
@Test
public void searchRequest() throws IOException {
SearchRequest searchRequest = new SearchRequest("my_blogs");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); // 構造查詢條件
QueryBuilder childQueryBuilder = JoinQueryBuilders
.hasChildQuery(
"comment",
QueryBuilders.matchAllQuery(),
ScoreMode.None).innerHit(new InnerHitBuilder().setSize(100));
queryBuilder.must(childQueryBuilder);
searchSourceBuilder.query(queryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 下面是對結果進行解析
SearchHits searchHits = searchResponse.getHits();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
System.out.println("index = " + hit.getIndex());
Map<String, Object> blogAsMap = hit.getSourceAsMap();
System.out.println("id:" + hit.getId());
for (Map.Entry<String, Object> kv : blogAsMap.entrySet()) {
System.out.println(kv.getKey() + ":" + kv.getValue().toString());
}
System.out.println("[InnerHits]");
Map<String, SearchHits> innerHits = hit.getInnerHits();
for (Map.Entry<String, SearchHits> commentHit : innerHits.entrySet()) {
String key = commentHit.getKey(); // 這個例子裡面, key = comment,因為InnerHits裡面只有comment型別的
for (SearchHit commentSource : commentHit.getValue().getHits()) {
if (commentSource != null) {
System.out.println("index = " + commentSource.getIndex());
System.out.println("id = " + commentSource.getId());
Map<String, Object> commentAsMap = commentSource.getSourceAsMap();
for (Map.Entry<String, Object> kv2 : commentAsMap.entrySet()) {
System.out.println(kv2.getKey() + ":" + kv2.getValue().toString());
}
}
}
}
System.out.println("------------------------------------------------------");
}
}
相當於如下查詢語句
GET /my_blogs/_search
{
"query": {
"bool": {
"must": [
{
"has_child": {
"query": {
"match_all": {}
},
"type": "comment",
"score_mode": "none",
"inner_hits": {
"size": 100
}
}
}
]
}
}
}
聚合
@Test
public void aggs() throws IOException {
SearchRequest searchRequest = new SearchRequest("my_blogs");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery(); // 構造查詢條件
searchSourceBuilder.query(queryBuilder);
// 設定為0後只返回聚合結果
searchSourceBuilder.size(0);
// 設定聚合欄位
List<String> aggKeys = new ArrayList<>();
aggKeys.add("author");
aggKeys.add("commentName");
aggKeys.forEach(aggKey -> {
searchSourceBuilder.aggregation(
AggregationBuilders.terms(aggKey).field(aggKey)
.size(10) // 針對這個欄位的聚合結果, 最多返回的個數
);
});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 獲取聚合結果
Aggregations aggregations = searchResponse.getAggregations();
// 解析聚合結果
aggKeys.forEach(aggKey -> {
Terms terms = aggregations.get(aggKey);
if (terms.getBuckets().size() > 0) {
for (Terms.Bucket bucket : terms.getBuckets()) {
String name = bucket.getKeyAsString(); // 聚合欄位
long count = bucket.getDocCount();
System.out.println(name + ":" + count);
}
}
});
}
相當於如下查詢語句
GET /my_blogs/_search
{
"size": 0,
"query": {
"match_all": {
"boost": 1
}
},
"aggregations": {
"author": {
"terms": {
"field": "author",
"size": 10,
"order": [
{
"_count": "desc"
},
{
"_key": "asc"
}
]
}
},
"commentName": {
"terms": {
"field": "commentName",
"size": 10,
"order": [
{
"_count": "desc"
},
{
"_key": "asc"
}
]
}
}
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結