Es basic usage

Time:2021-12-20

Create index

#Create index 
#"Dynamic": "strict" = = = "it is not allowed to add fields dynamically. If a new field is encountered, an exception will be thrown.
#"Dynamic": "true" = = = ", allowing dynamic addition of new fields. This is the default
#"Dynamic": "false" = = = = ignore new fields. On the basis of the original mapping, when there is a new field, it will not actively add a new mapping relationship, but only appear in the query as the query result.
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"
      }
    }
  }
}

The difference between keyword and text: text will be segmented;

The default format of date type is: “strict”_ date_ optional_ time||epoch_ millis”,file

View index information

GET my_blogs/_mapping

Delete index

DELETE /test_blogs

New document

#The specified document ID is blog1. If it is not specified, it will be generated automatically
#Add
POST my_blogs/_doc/blog1
{
  "author": "lzc",
  "title":"Learning ElasticSearch",
  "Content": "learning elasticsearch technology",
  "views": 0,
   "created": "2020-05-06 08:44:00"
}

POST my_blogs/_doc/blog2
{
  "author": "lzc",
  "title":"Learning Java",
  "Content": "learning Java technology",
  "views": 0,
   "created": "2020-05-06 08:44:00"
}

POST my_blogs/_doc/
{
  "author": "lzc",
  "title":"Learning RocketMQ",
  "Content": "learning rocketmq technology",
  "views": 0,
   "created": "2020-05-06 08:56:00"
}

#Query all
GET /my_blogs/_search
{
  "query": {
    "match_all": {}
  }
}

query

term、terms

Term query and terms query will find the exact term in the inverted index. It does not know the existence of the word separator. This query is suitable for the query with explicit values such as keyword, numeric, date, etc.

#Term query: query the document with a keyword in the author field
GET /my_blogs/_search
{
  "query": {
    "term": {
      "author": "lzc"
    }
  }
}
#Terms query: query documents with multiple keywords in the author field
GET /my_blogs/_search
{
  "query": {
    "terms": {
      "author": [
        "zhangsan",
        "lzc"
      ]
    }
  }
}

match、multi_match

The match query knows the existence of the word splitter, and will perform word segmentation on the field before querying

#It differs from term in that term is an exact query and match is a fuzzy query;
#Match will segment "learn rocketmq". The word segmentation rules are related to the word splitter and may be divided into "learn" and "rocketmq"
#Term can think of this as a word
GET /my_blogs/_search
{
  "query": {
    "match": {
      "Content": "learning rocketmq"
    }
  }
}

#Query multiple fields
GET /my_blogs/_search
{
  "query": {
    "multi_match": {
      "query": "RocketMQ",
      "fields": ["content","xxxx"]
    }
  }
}

_source

Specify the fields to return

#Only the author and title fields are returned
GET /my_blogs/_search
{
  "_source": ["author","title"], 
  "query": {
    "match_all": {}
  }
}

Bool query

must

The returned document must meet the conditions of the must clause and participate in the calculation of scores.

#Term query: query the document with a keyword in the author field
GET /my_blogs/_search
{
  "query": {
    "bool": {
      "must": [
        {"term":{"author":"lzc"}}
      ]
    }
  }
}
#Match multiple fields
GET /my_blogs/_search
{
  "query": {
    "bool": {
      "must": [
        {"term":{"title":"java"}},
        {"term":{"author":"zhangsan"}}
      ]
    }
  }
}

#Terms query: query documents with multiple keywords in a field
GET /my_blogs/_search
{
  "query": {
    "bool": {
      "must": [
        {"terms":{"author":["lzc","zhangsan"]}}
      ]
    }
  }
}

must_not

The returned document must not meet the requirement of must_ Not defined condition.

GET /my_blogs/_search
{
  "query": {
    "bool": {
      "must_not": [
        {"term":{"author":"zhangsan"}}
      ]
    }
  }
}

should

The returned document may meet the conditions of the should clause. In a Boolean query, if there is no must or filter and there are one or more should clauses, it can be returned as long as one is satisfied.minimum_should_matchThe parameter defines at least several clauses.

#Equivalent to or statement
GET /my_blogs/_search
{
  "query": {
    "bool": {
      "should": [
        {"term":{"author":"lzc"}},
        {"term":{"author":"zhangsan"}}
      ]
    }
  }
}

filter

The returned document must meet the conditions of the filter clause. However, it will not participate in the calculation of scores like must.

#Similar to and statement
GET /my_blogs/_search
{
  "query": {
    "bool": {
      "filter": [
        {"term":{"title":"java"}},
        {"term":{"author":"zhangsan"}}
      ]
    }
  }
}

exists

#The value of the query field author is not null or []
GET /my_blogs/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "author"
          }
        }
      ]
    }
  }
}

Highlight query

Single field query

GET /my_blogs/_search
{
  "query": {
    "match": {
      "content": "RocketMQ"
    }
  },
  "highlight": {
    "pre_tags": [
      "<tag1>"
    ],
    "post_tags": [
      "</tag1>"
    ],
    "fields": {
      "content": {}
    }
  }
}

Query results:

{
    "_index" : "my_blogs",
    "_type" : "_doc",
    "_id" : "Bfh853EBC1bB8l9gL99x",
    "_score" : 1.092264,
    "_source" : {
        "author" : "lzc",
        "title" : "Learning RocketMQ",
        "Content": "learning rocketmq technology",
        "views" : 0,
        "created" : "2020-05-06 08:56:00"
    },
    "highlight" : {
        "content" : [
            "Learn < tag1 > rocketmq < / tag1 > technology"
        ]
    }
}

Multi field query

GET /my_blogs/_search
{
    "query" : {
        "multi_match": { 
          "query": "RocketMQ" ,
          "fields" : [ "content", "title" ]
        }
    },
    "highlight" : {
        "pre_tags" : ["<tag1>"],
        "post_tags" : ["</tag1>"],
        "fields" : {
            "title": {},
            "content" : {}
        }
    }
}

remove document

#Delete by ID
DELETE my_blogs/_doc/blog9

#Delete by condition
POST my_blogs/_delete_by_query
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "author": {
              "value": "zhangsan"
            }
          }
        }
      ]
    }
  }
}

Modify document

#Modify according to ID
POST my_blogs/_update/blog1
{
  "doc": {
    "author":"lizc"
  }
}

# doc_ as_ Upsert is set to true. If the ID does not exist, it will be added
POST my_blogs/_update/blog2
{
  "doc": {
    "author":"lizhencheng",
    "Title": "study hard"
  },
  "doc_as_upsert" : true
}

join query

Elasticserch’s connection query can be implemented in two ways

  • nested
  • Parent and child Association query

nested

Create index

#Suppose it is used to store blogs and blog comments
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"
          }
        }
      }
    }
  }
}

New data

POST my_blogs/_doc/blog1
{
  "author": "lzc",
  "title":"Learning ElasticSearch",
  "Content": "learning elasticsearch technology",
  "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": "learning Java technology",
  "views": 0,
  "created": "2020-05-07 08:00:00",
  "comment":[
    {
      "commentName":"zhangsan",
      "commentContent":"commentContent4",
      "commentCreated":"2020-05-08 08:00:00"
    }
  ]
}

query

#Query author = lzc and 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

Create index

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"
      }
    }
  }
}

New data

#Add parent node
POST my_blogs/_doc/blog1
{
  "author": "lzc",
  "title":"Learning ElasticSearch",
  "Content": "learning elasticsearch technology",
  "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": "learning Java technology",
  "views": 0,
   "created": "2020-05-06 08:58:00",
   "blog_comment_relation": {
     "name":"blog"
   }
}

#Add child node record
#You need to specify routing as the ID of the parent node so that they are in the same partition. Whether it is a child node or a grandson node, routing refers to the parent node ID
#Parent specifies the parent element 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"
  }
}

query

#Has child query, return parent document
#"Inner_hits": {} = = > adding this will query the sub documents together. By default, only three pieces of data will be returned
#There are four attributes in "inner_hits"
#From: returns the offset of the result, such as "from": 2 = = > returns size pieces of data from the position with index 2
# size: inner_ The maximum number of hits returned. The default value is 3.
# size: inner_ Hits = > by default, the maximum can be set to 100, which can be accessed through index max_ inner_ result_ Window
#Sort: how to sort internal hits, such as "sort": [{"commentcreated": "desc"}]
#Name: the name of the specific internal hit definition in the response
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 query, return sub document
#"Inner_hits": {} = = > adding this will query the parent document together
POST /my_blogs/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "has_parent": {
            "parent_type": "blog",
            "query": {
              "match": {
                "_id": "blog1"
              }
            },
            "inner_hits": {}
          }
        }
      ]
    }
  }
}

compare

nested parent/child
advantage High reading performance Parent and child documents can be updated independently
shortcoming Each update requires updating the entire document Association relationship requires additional memory, and the query efficiency is relatively poor
scene Frequent query Frequent updates

polymerization

#If the size is 0, the document information will not be returned, only the aggregate information will be returned
GET /my_blogs/_search
{
    "size" : 0,
    "aggs" : { 
        "author_blog_counts" : { 
            "terms" : { 
              "field" : "author"
            }
        }
    }
}

Return results

{
  "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
        }
      ]
    }
  }
}

Reindex

Copy documents from one index to another.

#Will my_ Copy data from blogs to my_ blogs_ copy
POST _reindex
{
  "source": {
    "index": "my_blogs"
  },
  "dest": {
    "index": "my_blogs_copy"
  }
}

#Set the quantity. By default, the size is 1000
POST _reindex
{
  "size": 1, 
  "source": {
    "index": "my_blogs"
  },
  "dest": {
    "index": "my_blogs_copy"
  }
}

#Copy according to conditions
POST _reindex
{
  "size": 1000, 
  "source": {
    "index": "my_blogs",
    "query": {
      "bool": {
        "must": [
          {
            "term": {
              "author": {
                "value": "lzc"
              }
            }
          }
        ]
      }
    }
  },
  "dest": {
    "index": "my_blogs_copy"
  }
}

Automatic matching

www.elastic.co/guide/en/elasticsea…

paging

scroll

www.elastic.co/guide/en/elasticsea…

www.elastic.co/guide/en/elasticsea…

Java operation

to configure

<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>

Integration with springboot

elasticsearch.ip=localhost:9200

Configuration class

@Configuration
public class ESConfig {
    /**
     *The timeout is set to 5 minutes
     */
    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;
        }
    }
}

Create index

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"
      }
    }
  }
}

Write code

Official documents:www.elastic.co/guide/en/elasticsea…

newly added

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", "learn elasticsearch technology");
    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 index name
*@ param ID primary key ID. if NULL is passed in, it will be generated automatically
* @param routing
*@ param doc document content
*/
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;
}

Add or modify

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", "learn elasticsearch technology");
    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);
}


/**
*Add or modify
*@ param index document index
*@ param ID document ID
* @param routing
*@ param doc document field
*/
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);
}

Find by 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 index name
*@ param ID document 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;
}

Delete by ID

www.elastic.co/guide/en/elasticsea…

@Autowired
private RestHighLevelClient restHighLevelClient;

@Test
public void deleteDocumentById() throws IOException {
    deleteDocumentById("my_blogs", "comment1");
}

/**
*@ param index index name
*@ param ID document 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;
}

Condition query

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(); //  Construct query criteria
    searchSourceBuilder.query(queryBuilder);
    searchRequest.source(searchSourceBuilder);
    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    System.out.println();
}

QueryBuilders.matchAllQuery()Equivalent to the following query

GET /my_blogs/_search
{
  "query": {
    "match_all": {}
  }
}

Term query

//Construct query criteria
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); 
//Construct term
queryBuilder.must(QueryBuilders.termQuery("title", "Learning ElasticSearch"));

Equivalent to the following query

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(); //  Construct query criteria
    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);

    //The following is the analysis of the results
    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(); //  In this example, key = comment, because there are only comment types in innerhits
            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("------------------------------------------------------");
    }
}

Equivalent to the following query statement

GET /my_blogs/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "has_child": {
            "query": {
              "match_all": {}
            },
            "type": "comment",
            "score_mode": "none",
            "inner_hits": {
              "size": 100
            }
          }
        }
      ]
    }
  }
}

polymerization

@Test
public void aggs() throws IOException {
    SearchRequest searchRequest = new SearchRequest("my_blogs");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    QueryBuilder queryBuilder = QueryBuilders. matchAllQuery(); //  Construct query criteria
    searchSourceBuilder.query(queryBuilder);
    //When set to 0, only aggregate results are returned
    searchSourceBuilder.size(0);

    //Set aggregate fields
    List<String> aggKeys = new ArrayList<>();
    aggKeys.add("author");
    aggKeys.add("commentName");
    aggKeys.forEach(aggKey -> {
        searchSourceBuilder.aggregation(
            AggregationBuilders.terms(aggKey).field(aggKey)
            . Size (10) // the maximum number of aggregate results returned for this field
        );
    });

    searchRequest.source(searchSourceBuilder);
    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

    //Get aggregate results
    Aggregations aggregations = searchResponse.getAggregations();

    //Parse aggregation results
    aggKeys.forEach(aggKey -> {
        Terms terms = aggregations.get(aggKey);
        if (terms.getBuckets().size() > 0) {
            for (Terms.Bucket bucket : terms.getBuckets()) {
                String name = bucket. getKeyAsString(); //  Aggregate field
                long count = bucket.getDocCount();
                System.out.println(name + ":" + count);
            }
        }
    });
}

Equivalent to the following query statement

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"
          }
        ]
      }
    }
  }
}

This work adoptsCC agreement, reprint must indicate the author and the link to this article