admin
2020-05-06 24a8d17e007545f7426c48352109aa1a9c6587ee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
package org.fanli.elastic;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
 
import org.apache.http.HttpHost;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.fieldcaps.FieldCapabilities;
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse;
import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.MultiSearchResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.rankeval.EvalQueryQuality;
import org.elasticsearch.index.rankeval.EvaluationMetric;
import org.elasticsearch.index.rankeval.MetricDetail;
import org.elasticsearch.index.rankeval.PrecisionAtK;
import org.elasticsearch.index.rankeval.RankEvalRequest;
import org.elasticsearch.index.rankeval.RankEvalResponse;
import org.elasticsearch.index.rankeval.RankEvalSpec;
import org.elasticsearch.index.rankeval.RatedDocument;
import org.elasticsearch.index.rankeval.RatedRequest;
import org.elasticsearch.index.rankeval.RatedSearchHit;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.profile.ProfileResult;
import org.elasticsearch.search.profile.ProfileShardResult;
import org.elasticsearch.search.profile.aggregation.AggregationProfileShardResult;
import org.elasticsearch.search.profile.query.CollectorResult;
import org.elasticsearch.search.profile.query.QueryProfileShardResult;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import org.elasticsearch.search.suggest.term.TermSuggestion;
 
public class QueryUtils {
 
    private static String clusterName = "my-application";
    private static String host = "192.168.1.200";
    private static Integer port = 9200;
 
    // 相当于数据库名称
    public static String indexName = "shose";
 
    // 初始化api客户端
    public static RestHighLevelClient client = new RestHighLevelClient(
            RestClient.builder(new HttpHost(host, port, "http")));
 
    public static void SearchRequest() {
//        SearchRequest searchRequest = new SearchRequest(); // 如果没有参数,这将与所有索引冲突。
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
//        searchSourceBuilder.query(QueryBuilders.matchAllQuery()); 
//        searchRequest.source(searchSourceBuilder); 
 
//        SearchRequest searchRequest = new SearchRequest("posts"); 
//        searchRequest.routing("routing"); 
//        //     设置IndicesOptions控制如何解决不可用的索引以及如何扩展通配符表达式
//        searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen()); 
//        // 使用首选项参数,例如,执行搜索以偏爱本地碎片。默认设置是随机分片。
//        searchRequest.preference("_local"); 
 
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
        sourceBuilder.from(0); // 索引以开始搜索的选项。预设为0。
        sourceBuilder.size(5); // 返回的搜索命中次数的选项。默认为10
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // 设置一个可选的超时时间,以控制允许搜索的时间。
 
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("posts");
        searchRequest.source(sourceBuilder);
 
        // 创建与“用户”字段上的文本“ kimchy”匹配的全文匹配查询。
        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
        matchQueryBuilder.fuzziness(Fuzziness.AUTO); // 对匹配查询启用模糊匹配
        matchQueryBuilder.prefixLength(3); // 在匹配查询中设置前缀长度选项
        matchQueryBuilder.maxExpansions(10); // 设置最大扩展选项以控制查询的模糊过程
 
//        QueryBuilder matchQueryBuilder1 = QueryBuilders.matchQuery("user", "kimchy").fuzziness(Fuzziness.AUTO)
//                .prefixLength(3).maxExpansions(10);
//        sourceBuilder.query(matchQueryBuilder1);
 
        // 降序排列_score(默认)
        sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
        // 也按_id字段升序排序
        sourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC));
 
        // 搜索请求返回文档的内容,_source但是就像在Rest API中一样,您可以覆盖此行为。例如,您可以_source完全关闭检索:
        sourceBuilder.fetchSource(false);
 
        // 该方法还接受一个或多个通配符模式的数组,以控制以更细粒度的方式包含或排除哪些字段:
        String[] includeFields = new String[] { "title", "innerObject.*" };
        String[] excludeFields = new String[] { "user" };
        sourceBuilder.fetchSource(includeFields, excludeFields);
 
        // 突出显示搜索结果可以通过设置来实现HighlightBuilder的
        // SearchSourceBuilder。通过向中添加一个或多个HighlightBuilder.Field实例,
        // 可以为每个字段定义不同的突出显示行为HighlightBuilder
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title");
        highlightTitle.highlighterType("unified");
        highlightBuilder.field(highlightTitle);
        HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
        highlightBuilder.field(highlightUser);
        searchSourceBuilder.highlighter(highlightBuilder);
 
        // 聚合
        // 可以通过先创建适当的集合AggregationBuilder,然后将其设置在上,将聚合添加到搜索中 SearchSourceBuilder。
        // 在以下示例中,我们terms在公司名称上创建一个汇总,并在公司中员工的平均年龄上进行子汇总:
        SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();
        TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company").field("company.keyword");
        aggregation.subAggregation(AggregationBuilders.avg("average_age").field("age"));
        searchSourceBuilder2.aggregation(aggregation);
 
        // 要将“建议”添加到搜索请求中,请使用SuggestionBuilder可从SuggestBuilders工厂类轻松访问的实现之一。
        // 建议建设者需要添加到顶层SuggestBuilder,它本身可以在上设置 SearchSourceBuilder。
        SearchSourceBuilder searchSourceBuilder3 = new SearchSourceBuilder();
        // TermSuggestionBuilder为user字段和文本创建一个新的kmichy
        SuggestionBuilder termSuggestionBuilder = SuggestBuilders.termSuggestion("user").text("kmichy");
        SuggestBuilder suggestBuilder = new SuggestBuilder();
        suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
        searchSourceBuilder3.suggest(suggestBuilder);
 
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
 
            // 请求执行本身的有用信息,例如HTTP状态代码,执行时间或请求是提前终止还是超时:
            RestStatus status = searchResponse.status();
            TimeValue took = searchResponse.getTook();
            Boolean terminatedEarly = searchResponse.isTerminatedEarly();
            boolean timedOut = searchResponse.isTimedOut();
 
            // 响应还提供有关受搜索影响的分片总数以及成功与不成功分片的统计信息,从而提供有关分片级别执行的信息。可能的失败也可以通过遍历数组进行处理
            int totalShards = searchResponse.getTotalShards();
            int successfulShards = searchResponse.getSuccessfulShards();
            int failedShards = searchResponse.getFailedShards();
            for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
                // failures should be handled here
            }
 
            // 要访问返回的文档,我们需要首先获取SearchHits 响应中包含的内容:
            SearchHits hits = searchResponse.getHits();
            // 将SearchHits提供所有点击全局信息,比如命中总数或最大比分:
            TotalHits totalHits = hits.getTotalHits();
            // the total number of hits, must be interpreted in the context of
            // totalHits.relation
            long numHits = totalHits.value;
            // whether the number of hits is accurate (EQUAL_TO) or a lower bound of the
            // total (GREATER_THAN_OR_EQUAL_TO)
            TotalHits.Relation relation = totalHits.relation;
            float maxScore = hits.getMaxScore();
 
            // 嵌套在中的SearchHits是可以迭代的各个搜索结果:
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit hit : searchHits) {
                // SearchHit可访问索引一样,文档ID和每个搜索命中的得分基本信息:
                String index = hit.getIndex();
                String id = hit.getId();
                float score = hit.getScore();
 
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String documentTitle = (String) sourceAsMap.get("title");
                List<Object> users = (List<Object>) sourceAsMap.get("user");
                Map<String, Object> innerObject = (Map<String, Object>) sourceAsMap.get("innerObject");
            }
 
            // 可以从SearchHit结果中的每个检索出突出显示的文本片段。命中对象提供对HighlightField实例的字段名称映射的访问,每个实例包含一个或多个突出显示的文本片段:
            SearchHits hits2 = searchResponse.getHits();
            for (SearchHit hit : hits2.getHits()) {
                // 获得该title领域的亮点
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                HighlightField highlight = highlightFields.get("title");
                // 获取一个或多个包含突出显示的字段内容的片段
                Text[] fragments = highlight.fragments();
                String fragmentString = fragments[0].string();
            }
 
            Aggregations aggregations = searchResponse.getAggregations();
            Terms byCompanyAggregation = aggregations.get("by_company"); // 获取by_company条款汇总
            Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic"); // 获取带有密钥的存储桶 Elastic
            Avg averageAge = elasticBucket.getAggregations().get("average_age"); // average_age从该存储桶中获取子聚合
            double avg = averageAge.getValue();
 
            // 请注意,如果按名称访问聚合,则需要根据请求的聚合类型指定聚合接口,否则ClassCastException将抛出a:
            // 这将引发异常,因为“ by_company”是一个terms聚合,但是我们尝试将其作为range聚合进行检索
            Aggregation range = aggregations.get("by_company");
 
            // 也可以将所有聚合作为以聚合名称作为关键字的映射来访问。在这种情况下,必须明确地强制转换为正确的聚合接口:
            Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
            Terms companyAggregation = (Terms) aggregationMap.get("by_company");
 
            // 还有一些getter会将所有顶级聚合返回为列表:
            List<Aggregation> aggregationList = aggregations.asList();
 
            for (Aggregation agg : aggregations) {
                String type = agg.getType();
                if (type.equals(TermsAggregationBuilder.NAME)) {
                    Bucket elasticBucket2 = ((Terms) agg).getBucketByKey("Elastic");
                    long numberOfDocs = elasticBucket2.getDocCount();
                }
            }
 
            // 检索建议
            Suggest suggest = searchResponse.getSuggest();
            // 可以按名称检索建议。您需要将它们分配给“建议”类的正确类型(在此处TermSuggestion),否则ClassCastException抛出a
            TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
            for (TermSuggestion.Entry entry : termSuggestion.getEntries()) { // 遍历建议条目
                for (TermSuggestion.Entry.Option option : entry) { // 遍历一个条目中的选项
                    String suggestText = option.getText().string();
                }
            }
 
            // 检索Map的ProfileShardResult从SearchResponse
            Map<String, ProfileShardResult> profilingResults = searchResponse.getProfileResults();
            // 如果知道密钥,则可以通过分片的密钥来检索分析结果,否则,对所有分析结果进行迭代可能会更简单
            for (Map.Entry<String, ProfileShardResult> profilingResult : profilingResults.entrySet()) {
                // 检索标识ProfileShardResult属于哪个分片的密钥
                String key = profilingResult.getKey();
                // 检索ProfileShardResult给定分片的
                ProfileShardResult profileShardResult = profilingResult.getValue();
 
                // 所述ProfileShardResult对象本身包含一个或多个查询简档的结果,一个用于抵靠底层Lucene索引执
                List<QueryProfileShardResult> queryProfileShardResults = profileShardResult.getQueryProfileResults();
                for (QueryProfileShardResult queryProfileResult : queryProfileShardResults) {
 
                    // 每个都QueryProfileShardResult可以访问详细的查询树执行,以ProfileResult对象列表的形式返回
                    // 遍历概要文件结果
                    for (ProfileResult profileResult : queryProfileResult.getQueryResults()) {
                        // 检索Lucene查询的名称
                        String queryName = profileResult.getQueryName();
                        // 检索执行Lucene查询的毫秒数
                        long queryTimeInMillis = profileResult.getTime();
                        // 检索子查询的概要文件结果(如果有)
                        List<ProfileResult> profiledChildren = profileResult.getProfiledChildren();
                    }
 
                    // Rest API文档包含有关Lucene收集器性能分析信息的更多信息
                    // 检索Lucene收集器的分析结果
                    CollectorResult collectorResult = queryProfileResult.getCollectorResult();
                    // 检索Lucene收集器的名称
                    String collectorName = collectorResult.getName();
                    // 检索执行Lucene收集器所花费的毫秒数
                    Long collectorTimeInMillis = collectorResult.getTime();
                    // 检索子收集器的概要文件结果(如果有)
                    List<CollectorResult> profiledChildren = collectorResult.getProfiledChildren();
 
                }
 
                AggregationProfileShardResult aggsProfileResults = profileShardResult.getAggregationProfileResults();
                // 遍历聚合配置文件结果
                for (ProfileResult profileResult : aggsProfileResults.getProfileResults()) {
                    /// 检索聚合的类型(与用于执行聚合的Java类相对应)
                    String aggName = profileResult.getQueryName();
                    // 检索执行Lucene收集器所花费的毫秒数
                    long aggTimeInMillis = profileResult.getTime();
                    // 检索子聚合的概要文件结果(如果有)
                    List<ProfileResult> profiledChildren = profileResult.getProfiledChildren();
                }
            }
 
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
 
    // 多重搜索
    public static void SearchRequest2() {
        MultiSearchRequest request = new MultiSearchRequest();
        // 创建一个空文件SearchRequest,然后像填充常规文件一样填充它search。
        SearchRequest firstSearchRequest = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("user", "kimchy"));
        firstSearchRequest.source(searchSourceBuilder);
        request.add(firstSearchRequest);
 
        // 建立第二个SearchRequest并将其添加到中MultiSearchRequest。
        SearchRequest secondSearchRequest = new SearchRequest();
        searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("user", "luca"));
        secondSearchRequest.source(searchSourceBuilder);
        request.add(secondSearchRequest);
 
        SearchRequest searchRequest = new SearchRequest("posts");
        try {
            MultiSearchResponse response = client.msearch(request, RequestOptions.DEFAULT);
 
            MultiSearchResponse.Item firstResponse = response.getResponses()[0]; // 第一次搜索的项目
            assertNull(firstResponse.getFailure()); // 成功完成,因此getFailure返回null。
            SearchResponse searchResponse = firstResponse.getResponse();
            assertEquals(4, searchResponse.getHits().getTotalHits().value);
            MultiSearchResponse.Item secondResponse = response.getResponses()[1]; // 第二次搜索的项目。
            assertNull(secondResponse.getFailure());
            searchResponse = secondResponse.getResponse();
            assertEquals(1, searchResponse.getHits().getTotalHits().value);
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
 
    public static void FieldCapabilitiesRequest() {
        // fields参数支持通配符表示法。例如,提供text_* 将导致返回所有与表达式匹配的字段。
        FieldCapabilitiesRequest request = new FieldCapabilitiesRequest().fields("user").indices("posts", "authors",
                "contributors");
        request.indicesOptions(IndicesOptions.lenientExpandOpen());
        try {
            FieldCapabilitiesResponse response = client.fieldCaps(request, RequestOptions.DEFAULT);
 
            // 一个Map条目字段的可能的类型,在这种情况下keyword和text。
            Map<String, FieldCapabilities> userResponse = response.getField("user");
            FieldCapabilities textCapabilities = userResponse.get("keyword");
 
            boolean isSearchable = textCapabilities.isSearchable();
            boolean isAggregatable = textCapabilities.isAggregatable();
 
            // user字段类型为的所有索引keyword。
            String[] indices = textCapabilities.indices();
            // user字段不可搜索的这些索引的子集;如果始终可搜索,则返回null。
            String[] nonSearchableIndices = textCapabilities.nonSearchableIndices();
            // 这些索引的另一个子集,该user字段不可聚合;如果始终可聚合,则返回null。
            String[] nonAggregatableIndices = textCapabilities.nonAggregatableIndices();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
    public static void EvaluationMetric() {
        EvaluationMetric metric = new PrecisionAtK();
        List<RatedDocument> ratedDocs = new ArrayList<>();
        ratedDocs.add(new RatedDocument("posts", "1", 1));
        SearchSourceBuilder searchQuery = new SearchSourceBuilder();
        searchQuery.query(QueryBuilders.matchQuery("user", "kimchy"));
        RatedRequest ratedRequest = new RatedRequest("kimchy_query", ratedDocs, searchQuery);
        List<RatedRequest> ratedRequests = Arrays.asList(ratedRequest);
        RankEvalSpec specification = new RankEvalSpec(ratedRequests, metric);
        RankEvalRequest request = new RankEvalRequest(specification, new String[] { "posts" });
        try {
            RankEvalResponse response = client.rankEval(request, RequestOptions.DEFAULT);
 
            double evaluationResult = response.getMetricScore();// 综合评价结果
            assertEquals(1.0 / 3.0, evaluationResult, 0.0);
            Map<String, EvalQueryQuality> partialResults = response.getPartialResults();
 
            // 以查询ID为关键字的部分结果
            EvalQueryQuality evalQuality = partialResults.get("kimchy_query");
            assertEquals("kimchy_query", evalQuality.getId());
 
            // 每个部分结果的指标得分
            double qualityLevel = evalQuality.metricScore();
            assertEquals(1.0 / 3.0, qualityLevel, 0.0);
            List<RatedSearchHit> hitsAndRatings = evalQuality.getHitsAndRatings();
            RatedSearchHit ratedSearchHit = hitsAndRatings.get(2);
 
            // 额定搜索结果包含完整的信息 SearchHit
            assertEquals("3", ratedSearchHit.getSearchHit().getId());
            // Optional<Integer>如果文档在请求中未获得评级,则评级搜索命中还包含不存在的评级
            assertFalse(ratedSearchHit.getRating().isPresent());
            MetricDetail metricDetails = evalQuality.getMetricDetails();
            String metricName = metricDetails.getMetricName();
            // 指标详细信息以请求中使用的指标命名
            assertEquals(PrecisionAtK.NAME, metricName);
            PrecisionAtK.Detail detail = (PrecisionAtK.Detail) metricDetails;
            // 转换为请求中使用的指标后,指标详细信息可以深入了解指标计算的各个部分
            assertEquals(1, detail.getRelevantRetrieved());
            assertEquals(3, detail.getRetrieved());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    // 计数
    public static void CountRequest() {
        CountRequest countRequest = new CountRequest();
        // 大多数搜索参数已添加到中SearchSourceBuilder。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 向中添加match_all查询SearchSourceBuilder。
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        // 将添加SearchSourceBuilder到中CountRequest。
        countRequest.source(searchSourceBuilder);
 
        // 将请求限制为索引
        // 设置IndicesOptions控制如何解决不可用的索引以及如何扩展通配符表达式
        // 使用首选项参数,例如,执行搜索以偏爱本地碎片。默认设置是随机分片。
        CountRequest countRequest2 = new CountRequest("blog").routing("routing")
                .indicesOptions(IndicesOptions.lenientExpandOpen()).preference("_local");
 
        // 设置查询。可以是任何类型QueryBuilder
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
 
        CountRequest countRequest3 = new CountRequest();
        countRequest3.indices("blog", "author");
        countRequest3.source(sourceBuilder);
        
        
        try {
            CountResponse countResponse = client.count(countRequest, RequestOptions.DEFAULT);
            
            // 在CountResponse由执行所述计数API调用返回提供关于计数执行本身的请求等的HTTP状态代码,或者是否提前终止命中和细节的总数:
            long count = countResponse.getCount();
            RestStatus status = countResponse.status();
            Boolean terminatedEarly = countResponse.isTerminatedEarly();
            
            // 响应还提供有关受基础搜索影响的分片总数以及成功与不成功分片的统计信息,从而提供有关分片级别执行的信息。
            // 可能的失败也可以通过遍历数组进行处理,  ShardSearchFailures如以下示例所示:
            int totalShards = countResponse.getTotalShards();
            int skippedShards = countResponse.getSkippedShards();
            int successfulShards = countResponse.getSuccessfulShards();
            int failedShards = countResponse.getFailedShards();
            for (ShardSearchFailure failure : countResponse.getShardFailures()) {
                // failures should be handled here
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    
    public static void query() {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
        sourceBuilder.from(0); // 索引以开始搜索的选项。预设为0。
        sourceBuilder.size(5); // 返回的搜索命中次数的选项。默认为10
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // 设置一个可选的超时时间,以控制允许搜索的时间。
 
//        // 降序排列_score(默认)
//        sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//        // 也按_id字段升序排序
//        sourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC));
//
        // 该方法还接受一个或多个通配符模式的数组,以控制以更细粒度的方式包含或排除哪些字段:
        String[] includeFields = new String[] { "title", "innerObject.*" };
        String[] excludeFields = new String[] { "user" };
        sourceBuilder.fetchSource(includeFields, excludeFields);
        
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("posts");
        searchRequest.source(sourceBuilder);
        
        
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            
            SearchHits hits = searchResponse.getHits();
            
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit hit : searchHits) {
                // SearchHit可访问索引一样,文档ID和每个搜索命中的得分基本信息:
//                String index = hit.getIndex();
//                String id = hit.getId();
//                float score = hit.getScore();
 
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                
                
                String user = (String) sourceAsMap.get("user");
                String reason = (String) sourceAsMap.get("reason");
                String message = (String) sourceAsMap.get("message");
                String postDate = (String) sourceAsMap.get("postDate");
                String id = (String) sourceAsMap.get("_id");
                System.out.println(id +"  " + postDate +"  " + reason);
                System.out.println(reason +"  " + user);
                
//                List<Object> users = (List<Object>) sourceAsMap.get("user");
                //Map<String, Object> innerObject = (Map<String, Object>) sourceAsMap.get("innerObject");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    
    
    public static void main(String[] args) {
        query();
        System.out.println("------------ 测试结束 -------------------------");
    }
 
}