• ElasticSearch6.5.0【Java客户端之TransportClient】


    说明

    TransportClient:网上流传最多的客户端,目前最新版本

    Java REST Client:官方推荐的客户端,

    官方:我们要在Elasticsearch 7.0的版本中不赞成使用TransportClient,在Elasticsearch 8.0的版本中完全移除TransportClient。转而使用Java REST Client

    照这个势头看,现在都6.5了,8.0还会远嘛。使用客户端要注意版本对应的问题,最好版本完全一致,实在不行也要保障主版本一致,比如5.X6.X

    官方文档要对比着来看,我觉得好理解一些

    * https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html
    * https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

    TransportClient

    依赖

    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>transport</artifactId>
        <version>6.5.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.11.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-to-slf4j</artifactId>
        <version>2.11.1</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-client</artifactId>
        <version>6.5.0</version>
    </dependency>
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>6.5.0</version>
    </dependency>

    连接

    import org.elasticsearch.client.transport.TransportClient;
    import org.elasticsearch.common.settings.Settings;
    import org.elasticsearch.common.transport.TransportAddress;
    import org.elasticsearch.transport.client.PreBuiltTransportClient;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    
    public class TransportClientFactory {
    
        private TransportClientFactory(){}
    
        private static class Inner{
            private static final TransportClientFactory instance = new TransportClientFactory();
        }
    
        public static TransportClientFactory getInstance(){
            return Inner.instance;
        }
    
        public TransportClient getClient() throws UnknownHostException {
            Settings settings = Settings.builder()
                    .put("cluster.name", "my-elasticsearch")    // 默认的集群名称是elasticsearch,如果不是要指定
                    .build();
            return new PreBuiltTransportClient(settings)
                    //.addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9301))
                    .addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300));
        }
    
    }

     Index

    1. 添加文档

        public static TransportClient addDoc1() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            // 构建对象
            XContentBuilder builder = jsonBuilder()
                    .startObject()
                    .field("brand", "ANTA")
                    .field("color", "red")
                    .field("model", "S")
                    .field("postDate", new Date())
                    .endObject();
            // 转成JSON格式
            String json = Strings.toString(builder);
            /**
             * 参数1:index
             * 参数2:type
             * 参数3:id
             */
            IndexRequestBuilder indexRequestBuilder = client.prepareIndex("clothes", "young", "1");
            IndexResponse response = indexRequestBuilder.setSource(json, XContentType.JSON).get();
            System.out.println("Index:" + response.getIndex() + "," +
                    "Type:" + response.getType() + "," +
                    "ID:" + response.getId() + "," +
                    "Version:" + response.getVersion() + "," +
                    "Status:" + response.status().name()
            );
            return client;
        }

    执行结果:

    Index:clothes,Type:young,ID:1,Version:1,Status:CREATED

    2. 添加文档还可以不指定id,这个时候默认生成一个唯一id

        public static TransportClient addDoc2() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            // 构建对象
            XContentBuilder builder = jsonBuilder()
                    .startObject()
                    .field("brand", "YISHION")
                    .field("color", "Blue")
                    .field("model", "S")
                    .field("postDate", new Date())
                    .endObject();
            // 转成JSON格式
            String json = Strings.toString(builder);
            /**
             * 参数1:index
             * 参数2:type
             */
            IndexRequestBuilder indexRequestBuilder = client.prepareIndex("clothes", "young");
            IndexResponse response = indexRequestBuilder.setSource(json, XContentType.JSON).get();
            System.out.println("Index:" + response.getIndex() + "," +
                    "Type:" + response.getType() + "," +
                    "ID:" + response.getId() + "," +
                    "Version:" + response.getVersion() + "," +
                    "Status:" + response.status().name()
            );
            return client;
        }

    执行结果:

    Index:clothes,Type:young,ID:J5uAoWcBb9TcvgEh2GJ3,Version:1,Status:CREATED

    3. 根据id获取文档

        /**
         * 根据id获取
         * @throws IOException
         */
        public static TransportClient getDoc() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            // prepareGet 参数分别为index、type、id
            GetResponse response = client.prepareGet("clothes", "young", "1").get();
            String id = response.getId();
            String index = response.getIndex();
            Map<String, DocumentField> fields = response.getFields();
            // 返回的source,也就是数据源
            Map<String, Object> source = response.getSource();
            System.out.println("ID:" + id + ",Index:" + index);
            Set<String> fieldKeys = fields.keySet();
            for (String s : fieldKeys){
                DocumentField documentField = fields.get(s);
                String name = documentField.getName();
                List<Object> values = documentField.getValues();
                System.out.println(name + ":" + values.toString());
            }
            System.out.println("==========");
            Set<String> sourceKeys = source.keySet();
            for(String s : sourceKeys){
                Object o = source.get(s);
                System.out.println(s + ":" + o);
            }
            return client;
        }

    执行结果:

    ID:1,Index:clothes
    ==========
    color:red
    postDate:2018-12-12T08:18:21.509Z
    model:S
    brand:ANTA

    4. 根据id删除,我们删除那个默认生成的那个id

        /**
         * 根据id删除
         * @throws IOException
         */
        public static TransportClient delDoc() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            DeleteResponse response = client.prepareDelete("clothes", "young", "J5uAoWcBb9TcvgEh2GJ3").get();
            String id = response.getId();
            String index = response.getIndex();
            String status = response.status().name();
            System.out.println("ID:" + id + ",Index:" + index + ",Status:" + status);
            return client;
        }

    执行结果:

    ID:J5uAoWcBb9TcvgEh2GJ3,Index:clothes,Status:OK

    5. 根据条件删除

        /**
         * 根据条件删除
         * @throws IOException
         */
        public static TransportClient delDocByQuery() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            BulkByScrollResponse response = DeleteByQueryAction.INSTANCE.newRequestBuilder(client)
                    .filter(QueryBuilders.matchQuery("brand", "ANTA")) // 属性-值
                    .source("clothes")  // index
                    .get();
            long deleted = response.getDeleted();
            System.out.println(deleted);
            return client;
        }

    执行结果:

    1

    这里第一次遇到QueryBuilders,这个东西很常用,回头我介绍这个类。

    根据条件删除还可以指定type

        DeleteByQueryRequestBuilder builder = DeleteByQueryAction.INSTANCE.newRequestBuilder(client);
        builder.filter(QueryBuilders.matchQuery("brand", "ANTA")) // 属性-值
                .source("clothes")  // index
                .source().setTypes("young"); // type
        BulkByScrollResponse response = builder.get();

    6. 批量插入(这个bulk不仅可以批量创建,也可以更新或者删除)

        /**
         * 批量插入
         * @throws IOException
         */
        public static TransportClient bulkDoc() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            BulkRequestBuilder bulk = client.prepareBulk();
            bulk.add(client.prepareIndex("car", "model", "1")
                    .setSource(jsonBuilder()
                            .startObject()
                            .field("name", "法拉利488")
                            .field("price", "315.50-418.80万")
                            .field("postDate", new Date())
                            .endObject()
                    )
            );
            bulk.add(client.prepareIndex("car", "model", "2")
                    .setSource(jsonBuilder()
                            .startObject()
                            .field("name", "法拉利LaFerrari")
                            .field("price", "2250.00万")
                            .field("postDate", new Date())
                            .endObject()
                    )
            );
            bulk.add(client.prepareIndex("car", "model", "3")
                    .setSource(jsonBuilder()
                            .startObject()
                            .field("name", "法拉利GTC4Lusso")
                            .field("price", "322.80-485.80万")
                            .field("postDate", new Date())
                            .endObject()
                    )
            );
            BulkResponse responses = bulk.get();
            String status = responses.status().name();
            System.out.println(status);
            return client;
        }

    执行结果:

    OK

    7. 获取多个结果

        /**
         * 批量获取
         * @throws IOException
         */
        public static TransportClient multiGetDoc() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            MultiGetResponse multiGetItemResponses = client.prepareMultiGet()
                    // 可以指定多个index,多个id
                    .add("clothes", "young", "1", "2")
                    .add("car", "model", "1","2","3")
                    .get();
    
            for (MultiGetItemResponse itemResponse : multiGetItemResponses) {
                GetResponse response = itemResponse.getResponse();
                if (response.isExists()) {
                    String json = response.getSourceAsString();
                    System.out.println(json);
                }
            }
            return client;
        }

    执行结果:由于之前clothes里面没数据了,所以只显示了下面三条数据

    {"name":"法拉利488","price":"315.50-418.80万","postDate":"2018-12-12T08:38:09.107Z"}
    {"name":"法拉利LaFerrari","price":"2250.00万","postDate":"2018-12-12T08:38:09.129Z"}
    {"name":"法拉利GTC4Lusso","price":"322.80-485.80万","postDate":"2018-12-12T08:38:09.129Z"}

    8. 更新

        /**
         * 更新方式一:通过UpdateRequest
         * @throws IOException
         * @throws ExecutionException
         * @throws InterruptedException
         */
        public static TransportClient updateDoc1() throws IOException, ExecutionException, InterruptedException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            UpdateRequest updateRequest = new UpdateRequest();
            updateRequest.index("car"); // 指定index
            updateRequest.type("model");// 指定type
            updateRequest.id("3");       // 指定id
            // 更新内容
            updateRequest.doc(jsonBuilder()
                    .startObject()
                    .field("name", "Aventador")
                    .field("price", "630.00-755.94万")
                    .field("postDate", new Date())
                    .field("extra", "Extra Data")   // 不存在的会自动添加
                    .endObject());
            UpdateResponse updateResponse = client.update(updateRequest).get();
            System.out.println(updateResponse.status().name());
            return client;
        }

    执行结果:

    OK

     在Kibana上查看结果:GET /car/model/3

    客户端有两种请求方式,一种是***Request(比如UpdateRequest ),另一种是prepare***(比如prepareUpdate),我更喜欢用prepare***

        /**
         * 更新方式二:通过prepareUpdate
         * @throws IOException
         */
        public static TransportClient updateDoc2() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            client.prepareUpdate("car", "model", "1")
                    .setDoc(jsonBuilder()
                            .startObject()
                            .field("name", "法拉利812 Superfast")
                            .field("price", "498.80万")
                            .field("postDate", new Date())
                            .endObject()
                    )
                    .get();
            return client;
        }

     9. upset更新

        /**
         * 文档存在则更新doc,不存在则添加upsert
         * @throws IOException
         * @throws ExecutionException
         * @throws InterruptedException
         */
        public static TransportClient upsert() throws IOException, ExecutionException, InterruptedException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            IndexRequest indexRequest = new IndexRequest("clothes", "young", "3")
                    .source(jsonBuilder()
                            .startObject()
                            .field("brand", "Pierre Cardin")
                            .field("color", "Black")
                            .field("model", "L")
                            .field("postDate", new Date())
                            .endObject());
            UpdateRequest updateRequest = new UpdateRequest("clothes", "young", "3")
                    .doc(jsonBuilder()
                            .startObject()
                            .field("model", "XL")
                            .endObject())
                    .upsert(indexRequest);
            UpdateResponse response = client.update(updateRequest).get();
            System.out.println(response.status().name());
            return client;
        }

    什么意思呢,如果文档存在,则只更新model字段,相反会添加IndexRequest里面的内容。

    第一次执行:(文档不存在) 

    CREATED

     GET /clothes/young/3

     

    第二次执行:

    OK

    查看Kibana

    10. bulkProcessor 另外一个批量工具

     基本的配置

    .setBulkActions(10000)  // 每10000个request,bulk一次
    .setBulkSize(new ByteSizeValue(5, ByteSizeUnit.MB)) // 每5M的数据刷新一次
    .setFlushInterval(TimeValue.timeValueSeconds(5))    // 每5s刷新一次,而不管有多少数据量
    .setConcurrentRequests(0)   // 设置并发请求的数量。值为0意味着只允许执行一个请求。值为1意味着在积累新的批量请求时允许执行1个并发请求。
    .setBackoffPolicy(  // 设置一个自定义的重试策略,该策略最初将等待100毫秒,按指数增长,最多重试3次。当一个或多个批量项请求失败时,如果出现EsRejectedExecutionException异常,将尝试重试,该异常表明用于处理请求的计算资源太少。要禁用backoff,请传递BackoffPolicy.noBackoff()。
            BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3))

    测试

        /**
         * 造数据
         * @throws IOException
         */
        public static TransportClient scrollSearchPreData() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            BulkProcessor bulkProcessor = BulkProcessor.builder(
                    client,
                    new BulkProcessor.Listener() {
                        @Override
                        public void beforeBulk(long executionId, BulkRequest request) {
                            // bulk 执行之前
                            System.out.println("beforeBulk-----" + request.getDescription());
                        }
    
                        @Override
                        public void afterBulk(long executionId,
                                              BulkRequest request,
                                              BulkResponse response) {
                            // bulk 执行之后
                            System.out.println("afterBulk------" + request.getDescription() + ",是否有错误:" + response.hasFailures());
                        }
    
                        @Override
                        public void afterBulk(long executionId,
                                              BulkRequest request,
                                              Throwable failure) {
                            //bulk 失败
                            System.out.println("报错-----" + request.getDescription() + "," + failure.getMessage());
                        }
                    })
                    .setBulkActions(100)  // 每100个request,bulk一次
                    .setConcurrentRequests(0)   // 设置并发请求的数量。值为0意味着只允许执行一个请求。值为1意味着在积累新的批量请求时允许执行1个并发请求。
                    .build();
            Random random = new Random();
            for (int i = 1; i <= 1000; i++){
                bulkProcessor.add(new IndexRequest("book", "elasticsearch", i+"").source(jsonBuilder()
                        .startObject()
                        .field("name", "book_" + i)
                        .field("price", random.nextDouble()*1000)
                        .field("postDate", new Date())
                        .endObject()));
            }
            bulkProcessor.flush();
            bulkProcessor.close();
            return client;
        }

    执行结果:1000条数据,bulk10次

    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false
    beforeBulk-----requests[100], indices[book]
    afterBulk------requests[100], indices[book],是否有错误:false

    11. scroll(让数据都滚出来)

        /**
         * 当搜索请求返回一个结果的“页面”时,滚动API可以用于从一个搜索请求检索大量的结果(甚至所有结果)
         * 其方式与在传统数据库中使用游标非常类似。滚动不是为了实时的用户请求,而是为了处理大量的数据
         * @throws UnknownHostException
         */
        public static TransportClient scrollSearch() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse response = client.prepareSearch("book")
                    .addSort("price", SortOrder.ASC)
                    .setScroll(new TimeValue(30000))
                    .setSize(1000).get();   // 每次滚出1000条就返回
            do {
                System.out.println("========Begin=======");
                for (SearchHit hit : response.getHits().getHits()) {
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("========End=======");
                response = client.prepareSearchScroll(response.getScrollId()).setScroll(new TimeValue(30000)).execute().actionGet();
            } while(response.getHits().getHits().length != 0);
            return client;
        }

    执行结果:

    ========Begin=======
    {"name":"book_233","price":0.7903630819869889,"postDate":"2018-12-12T09:27:32.629Z"}
    {"name":"book_46","price":1.9862330698061648,"postDate":"2018-12-12T09:27:30.722Z"}
    {"name":"book_18","price":2.8024592316934216,"postDate":"2018-12-12T09:27:30.721Z"}
    {"name":"book_512","price":3.5739663933835875,"postDate":"2018-12-12T09:27:33.275Z"}
    {"name":"book_275","price":5.449351054677254,"postDate":"2018-12-12T09:27:32.632Z"}
    {"name":"book_112","price":8.035476335226166,"postDate":"2018-12-12T09:27:32.424Z"}
    ...此处省略
    ========End=======

    12. 根据查询更新

        /**
         * 当版本匹配时,updateByQuery更新文档并增加版本号。
         * 所有更新和查询失败都会导致updateByQuery中止。这些故障可从BulkByScrollResponse#getBulkFailures方法中获得。
         * 任何成功的更新都会保留并不会回滚。当第一个失败导致中止时,响应包含由失败的批量请求生成的所有失败。
         * 当文档在快照时间和索引请求过程时间之间发生更改时,就会发生版本冲突
         * 为了防止版本冲突导致updateByQuery中止,设置abortOnVersionConflict(false)。
         * ScriptType.INLINE:在大量查询中指定内联脚本并动态编译。它们将基于脚本的lang和代码进行缓存。
         * ScriptType.STORED:存储的脚本作为{@link org.elasticsearch.cluster.ClusterState}的一部分保存基于用户请求。它们将在查询中首次使用时被缓存。
         * https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs-update-by-query.html
         * https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html
         * @throws UnknownHostException
         */
        public static TransportClient updateByQuery() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            UpdateByQueryRequestBuilder updateByQuery = UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
            updateByQuery.source("book")
                    .size(100)  // 尝试获取的最大文档数
                    .filter(QueryBuilders.termsQuery("name","book_233", "book_46", "book_18", "book_512"))  // 注意term,value要变成小写!!
                    // 以下脚本:保留id=781的,删除id=316的,其它的价格都变为79
                    .script(new Script(
                            ScriptType.INLINE,Script.DEFAULT_SCRIPT_LANG,
                            "if (ctx._source['id'] == 781) {"
                                    + "  ctx.op='noop'" // ctx.op='noop'  不做处理
                                    + "} else if (ctx._source['id'] == '316') {"
                                    + "  ctx.op='delete'"   // ctx.op='delete'删除
                                    + "} else {"
                                    + "ctx._source['price'] = 79}",
                             Collections.emptyMap()))
                    .abortOnVersionConflict(false); // 版本冲突策略:abortOnVersionConflict 版本冲突时不终止
    //                .source().setTypes("young") // 指定type
    //                .setSize(10)   // 返回搜索的命中数
    //                .addSort("postDate", SortOrder.DESC);
            BulkByScrollResponse response = updateByQuery.get();
            System.out.println("Deleted:" + response.getDeleted() + ",Created:" +
                    response.getCreated() + ",Updated:" + response.getUpdated() + ",Noops:" + response.getNoops());
    
            List<BulkItemResponse.Failure> failures = response.getBulkFailures();
            System.out.println(failures.size());
            // 如果目标值是Cat,更新内容也是Cat,则不会去更新
            return client;
        }

    执行结果:(这个term查询有点坑,value必须为小写,并且不能带-,我之前生成的格式为book-100,结果查询不出来。。。)

    Deleted:0,Created:0,Updated:4,Noops:0
    0

    查看数据:

    GET /book/elasticsearch/_mget
    {
        "ids" : ["233", "46", "18", "512"]
    }

    结果:

    {
      "docs" : [
        {
          "_index" : "book",
          "_type" : "elasticsearch",
          "_id" : "233",
          "_version" : 2,
          "found" : true,
          "_source" : {
            "price" : 79,
            "name" : "book_233",
            "postDate" : "2018-12-12T09:27:32.629Z"
          }
        },
        {
          "_index" : "book",
          "_type" : "elasticsearch",
          "_id" : "46",
          "_version" : 2,
          "found" : true,
          "_source" : {
            "price" : 79,
            "name" : "book_46",
            "postDate" : "2018-12-12T09:27:30.722Z"
          }
        },
        {
          "_index" : "book",
          "_type" : "elasticsearch",
          "_id" : "18",
          "_version" : 2,
          "found" : true,
          "_source" : {
            "price" : 79,
            "name" : "book_18",
            "postDate" : "2018-12-12T09:27:30.721Z"
          }
        },
        {
          "_index" : "book",
          "_type" : "elasticsearch",
          "_id" : "512",
          "_version" : 2,
          "found" : true,
          "_source" : {
            "price" : 79,
            "name" : "book_512",
            "postDate" : "2018-12-12T09:27:33.275Z"
          }
        }
      ]
    }

    13. 简单查询

        /**
         * 简单查询【通配符查询,筛选价格范围,设定返回数量,排序】
         * @throws UnknownHostException
         */
        public static TransportClient search() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse response = client.prepareSearch("book")    // index,可以多个
                    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                    .setQuery(QueryBuilders.wildcardQuery("name", "*book_1*"))          // Query
                    .setPostFilter(QueryBuilders.rangeQuery("price").from(800).to(900))     // Filter
                    .setFrom(0).setSize(100).setExplain(true).addSort("postDate", SortOrder.DESC)
                    .get();
            response.getHits().forEach(e ->{
                System.out.println(e.getSourceAsString());
            });
            return client;
        }

    执行结果:

    {"name":"book_1000","price":811.3812414198577,"postDate":"2018-12-12T09:27:34.095Z"}
    {"name":"book_194","price":828.6484294585816,"postDate":"2018-12-12T09:27:32.433Z"}
    {"name":"book_171","price":839.1475764183831,"postDate":"2018-12-12T09:27:32.432Z"}
    {"name":"book_170","price":869.7835076374234,"postDate":"2018-12-12T09:27:32.431Z"}
    {"name":"book_161","price":838.5131747806441,"postDate":"2018-12-12T09:27:32.429Z"}
    {"name":"book_153","price":805.041724108352,"postDate":"2018-12-12T09:27:32.429Z"}
    {"name":"book_154","price":893.982844708382,"postDate":"2018-12-12T09:27:32.429Z"}
    {"name":"book_105","price":883.039302643907,"postDate":"2018-12-12T09:27:32.424Z"}
    {"name":"book_19","price":877.0523728410054,"postDate":"2018-12-12T09:27:30.721Z"}

    14. 多个查询MultiSearch

        /**
         * 多个查询
         */
        public static TransportClient multiSearch() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            // 第一个查询
            SearchRequestBuilder srb1 = client
                    .prepareSearch("book")
                    .setQuery(QueryBuilders.queryStringQuery("book_9*").field("name"))
                    .setFrom(0)    // 开始位置
                    .setSize(10);   // 设置返回的最大条数
            // 第二个查询
            SearchRequestBuilder srb2 = client
                    .prepareSearch("car")
                    .setQuery(QueryBuilders.queryStringQuery("*r*"))
                    .setSize(10);
            // 组合
            MultiSearchResponse sr = client.prepareMultiSearch()
                    .add(srb1)
                    .add(srb2)
                    .get();
    
            // You will get all individual responses from MultiSearchResponse#getResponses()
            long nbHits = 0;
            for (MultiSearchResponse.Item item : sr.getResponses()) {
                SearchResponse response = item.getResponse();
                response.getHits().forEach(e ->{
                    System.out.println(e.getSourceAsString());
                });
                long hits = response.getHits().getTotalHits();
                System.out.println("Hits:" + hits);
                nbHits += hits;
            }
            System.out.println("Total:" + nbHits);
            return client;
        }

    执行结果:

    {"name":"book_92","price":176.35847694096162,"postDate":"2018-12-12T09:27:30.724Z"}
    {"name":"book_98","price":611.4318589503413,"postDate":"2018-12-12T09:27:30.724Z"}
    {"name":"book_99","price":214.4653626273969,"postDate":"2018-12-12T09:27:30.724Z"}
    {"name":"book_900","price":973.3382073380857,"postDate":"2018-12-12T09:27:33.892Z"}
    {"name":"book_915","price":35.30856326485343,"postDate":"2018-12-12T09:27:34.091Z"}
    {"name":"book_922","price":299.58144612743064,"postDate":"2018-12-12T09:27:34.091Z"}
    {"name":"book_930","price":591.6598815227311,"postDate":"2018-12-12T09:27:34.092Z"}
    {"name":"book_933","price":287.18727780940037,"postDate":"2018-12-12T09:27:34.092Z"}
    {"name":"book_935","price":693.6036227965725,"postDate":"2018-12-12T09:27:34.092Z"}
    {"name":"book_942","price":701.4129722487066,"postDate":"2018-12-12T09:27:34.092Z"}
    Hits:111
    {"name":"法拉利LaFerrari","price":"2250.00万","postDate":"2018-12-12T08:38:09.129Z"}
    {"name":"Aventador","price":"630.00-755.94万","postDate":"2018-12-12T08:49:01.736Z","extra":"Extra Data"}
    Hits:2
    Total:113

     聚合

    15. 聚合查询

        /**
         * 聚合查询
         * 搜索是查找某些具体的文档.然而聚合就是对这些搜索到的文档进行统计
         * https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html
         * https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-aggs.html
         * https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-search-aggs.html
         * 可以在聚合中定义子聚合
         * @return
         * @throws UnknownHostException
         */
        public static TransportClient aggregationsSearch() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse sr = client.prepareSearch("book")
                    .setQuery(QueryBuilders.matchAllQuery())
                    .addAggregation(
                            AggregationBuilders.stats("agg1").field("price")
                    )
                    .addAggregation(
                            AggregationBuilders.dateHistogram("agg2")
                                    .field("postDate")
                                    .dateHistogramInterval(DateHistogramInterval.YEAR)
                    )
                    .get(); // Short version of execute().actionGet().
    
            // Get your facet results
            Aggregation agg1 = sr.getAggregations().get("agg1");
            System.out.println(agg1.getClass());    // class org.elasticsearch.search.aggregations.metrics.stats.InternalStats
            Aggregation agg2 = sr.getAggregations().get("agg2");
            System.out.println(agg2.getClass());    // class org.elasticsearch.search.aggregations.bucket.histogram.InternalDateHistogram
            return client;
        }

    15.1 metrics聚合

        /**
         * metrics聚合
         * 主要为了统计信息
         * org.elasticsearch.search.aggregations.metrics.percentiles.Percentiles
         * org.elasticsearch.search.aggregations.metrics.percentiles.PercentileRanks
         * org.elasticsearch.search.aggregations.metrics.cardinality.Cardinality
         * 地理位置聚合:https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_metrics_aggregations.html#java-aggs-metrics-geobounds
         * https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_metrics_aggregations.html#java-aggs-metrics-tophits
         * https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_metrics_aggregations.html#java-aggs-metrics-scripted-metric
         * @return
         * @throws UnknownHostException
         */
        public static TransportClient metricsAggregationsSearch() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse sr = client.prepareSearch("book")
                    .setQuery(QueryBuilders.matchAllQuery())
                    .addAggregation(
                            AggregationBuilders.min("agg1").field("price")
                    )
                    .addAggregation(
                            AggregationBuilders.max("agg2").field("price")
                    )
                    .addAggregation(
                            AggregationBuilders.sum("agg3").field("price")
                    )
                    .addAggregation(
                            AggregationBuilders.avg("agg4").field("price")
                    )
                    .addAggregation(
                            AggregationBuilders.count("agg5").field("price")
                    )
                    .addAggregation(
                            AggregationBuilders.stats("agg6").field("price")
                    )
                    .get();
            Min agg1 = sr.getAggregations().get("agg1");
            Max agg2 = sr.getAggregations().get("agg2");
            Sum agg3 = sr.getAggregations().get("agg3");
            Avg agg4 = sr.getAggregations().get("agg4");
            ValueCount agg5 = sr.getAggregations().get("agg5");
            Stats agg6 = sr.getAggregations().get("agg6");
            System.out.println("Min:" + agg1.getValue() + ",Max:" + agg2.getValue() + ",Sum:" + agg3.getValue() + ",Avg:" + agg4.getValue() + ",Count:" + agg5.getValue() +
                    ",Stats:(" + agg6.getMin() + "," + agg6.getMax() + "," + agg6.getSum() + "," + agg6.getAvg() + "," + agg6.getCount() + ")");
            return client;
        }

    执行结果:

    Min:5.449350833892822,Max:999.3211669921875,Sum:502966.58267736435,Avg:502.96658267736433,Count:1000,Stats:(5.449350833892822,999.3211669921875,502966.58267736435,502.96658267736433,1000)

    15.2地理位置聚合(计算坐标的左上/右下边界值)

        /**
         * 准备地理位置信息
         * @return
         * @throws IOException
         */
        public static TransportClient geoSearchPreData() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            // 建立索引
            CreateIndexResponse indexResponse = client.admin().indices().prepareCreate("area")
                    .setSettings(Settings.builder()
                            .put("index.number_of_shards", 1)   // 分片
                            .put("index.number_of_replicas", 1) // 副本
                    )
                    .addMapping("hospital", "message", "type=text", "location", "type=geo_point")
                    .get();
            System.out.println("Index:" + indexResponse.index() + ",ACK:" + indexResponse.isAcknowledged());
            BulkProcessor bulkProcessor = BulkProcessor.builder(
                    client,
                    new BulkProcessor.Listener() {
                        @Override
                        public void beforeBulk(long executionId, BulkRequest request) {
                            // bulk 执行之前
                            System.out.println("beforeBulk-----" + request.getDescription());
                        }
    
                        @Override
                        public void afterBulk(long executionId,
                                              BulkRequest request,
                                              BulkResponse response) {
                            // bulk 执行之后
                            System.out.println("afterBulk------" + request.getDescription() + ",hasFailures:" + response.hasFailures());
                        }
    
                        @Override
                        public void afterBulk(long executionId,
                                              BulkRequest request,
                                              Throwable failure) {
                            //bulk 失败
                            System.out.println("报错-----" + request.getDescription() + "," + failure.getMessage());
                        }
                    })
                    .setBulkActions(100)  // 每100个request,bulk一次
                    .setConcurrentRequests(0)   // 设置并发请求的数量。值为0意味着只允许执行一个请求。值为1意味着在积累新的批量请求时允许执行1个并发请求。
                    .build();
            Random random = new Random();
            for (int i = 1; i <= 200; i++){
                String lo = new DecimalFormat("#.############").format(random.nextDouble() * 100);
                String la = new DecimalFormat("#.############").format(random.nextDouble() * 100);
                bulkProcessor.add(new IndexRequest("area", "hospital", i+"").source(jsonBuilder()
                        .startObject()
                        .field("name", "hospital-" + i)
                        .field("location", lo + "," + la)
                        .endObject()));
            }
            bulkProcessor.flush();
            bulkProcessor.close();
            return client;
        }
    
        /**
         * 地理信息查询
         * @return
         * @throws UnknownHostException
         */
        public static TransportClient geoAggregation() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse sr = client.prepareSearch("area")
                    .setQuery(QueryBuilders.matchQuery("name", "hospital-1"))
                    .addAggregation(
                            AggregationBuilders.geoBounds("agg").field("location").wrapLongitude(true)
                    )
                    .get();
            GeoBounds agg = sr.getAggregations().get("agg");
            GeoPoint left = agg.topLeft();
            GeoPoint right = agg.bottomRight();
            System.out.println(left + " | " + right);
            return client;
        }

    执行结果:

    89.9911705031991, 0.03342803567647934 | 0.049703302793204784, 99.9249867349863

    15.3桶聚合

        /**
         * 桶聚合,我这里只列举了部分
         * https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_bucket_aggregations.html
         * @return
         * @throws UnknownHostException
         */
        public static TransportClient bucketAggregationsSearch() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse sr = client.prepareSearch()
                    .setQuery(QueryBuilders.matchAllQuery())
    //                .addAggregation(AggregationBuilders
    //                        .global("agg0")
    //                        .subAggregation(AggregationBuilders.terms("sub_agg").field("name"))
    //                )
                    .addAggregation(AggregationBuilders
                            .filter("agg1", QueryBuilders.termQuery("name", "book_199")))
                    .addAggregation(AggregationBuilders
                            .filters("agg2",
                                    new FiltersAggregator.KeyedFilter("key1", QueryBuilders.termQuery("name", "book_1")),
                                    new FiltersAggregator.KeyedFilter("key2", QueryBuilders.termQuery("name", "book_52"))
                                    ))
                    .get();
    
    //        Global agg0 = sr.getAggregations().get("agg0");
    //        System.out.println("GlobalCount:" + agg0.getDocCount());
    
            Filter agg1 = sr.getAggregations().get("agg1");
            System.out.println("FilterCount:" + agg1.getDocCount());
    
            Filters agg2 = sr.getAggregations().get("agg2");
            for (Filters.Bucket entry : agg2.getBuckets()) {
                String key = entry.getKeyAsString();            // bucket key
                long docCount = entry.getDocCount();            // Doc count
                System.out.println("key [" + key + "], doc_count ["+ docCount +"]");
            }
            return client;
        }

    执行结果:Global会屏蔽其它的Agg

    FilterCount:1
    key [key1], doc_count [1]
    key [key2], doc_count [1]

    查询DSL

    16. Query DSL

    16.1 MatchAll,最简单的查询,它会匹配所有文档

    client.prepareSearch().setQuery(QueryBuilders.matchAllQuery());

    16.2 全文检索【高级全文查询通常用于在全文字段(如电子邮件正文)上运行全文查询,在执行之前有分析的过程

    16.2.1 Match Query(全文查询的标准查询,包括模糊匹配和短语或邻近查询)

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("book")
                    .setQuery(QueryBuilders
                            .matchQuery("name", "book_1")
                            .fuzziness(Fuzziness.AUTO)  // 模糊查询
                            .zeroTermsQuery(MatchQuery.ZeroTermsQuery.ALL)  // 与MatchAll等价,匹配所有文档。默认none,不匹配任何文档
                    ).get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:(为什么会命中250条呢?这是因为模糊查询,如果你注释掉模糊查询,就只会查到一条)

    {"name":"book_1","price":541.5683324629698,"postDate":"2018-12-12T09:27:30.695Z"}
    {"name":"book_2","price":859.0268161692424,"postDate":"2018-12-12T09:27:30.720Z"}
    {"name":"book_4","price":666.0331749730802,"postDate":"2018-12-12T09:27:30.720Z"}
    {"name":"book_6","price":797.3826369337273,"postDate":"2018-12-12T09:27:30.720Z"}
    {"name":"book_15","price":764.0761667524818,"postDate":"2018-12-12T09:27:30.721Z"}
    {"name":"book_51","price":969.2863955131567,"postDate":"2018-12-12T09:27:30.722Z"}
    {"name":"book_3","price":467.29468328850055,"postDate":"2018-12-12T09:27:30.720Z"}
    {"name":"book_11","price":365.2274741512962,"postDate":"2018-12-12T09:27:30.720Z"}
    {"name":"book_17","price":498.8900836459158,"postDate":"2018-12-12T09:27:30.721Z"}
    {"name":"book_31","price":377.2822748558652,"postDate":"2018-12-12T09:27:30.721Z"}
    命中:250

    16.2.2 Multi Match Query(标准查询的多字段版本)

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    // 关键字Aventador,匹配多个字段*ame、brand。字段名称可以使用通配符
                    .setQuery(QueryBuilders.multiMatchQuery("Aventador", "*ame","brand"))
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    {"name":"Aventador","price":"630.00-755.94万","postDate":"2018-12-12T08:49:01.736Z","extra":"Extra Data"}
    命中:1

    16.2.3 Common Terms Query(一个更专业的查询,偏好不常见的关键字)

    ...待补充

    16.2.4 Query String Query(解析输入并围绕操作符拆分文本,每个文本部分都是独立分析的)

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    // 关键字和字段【均可以】可以使用通配符(?匹配一个字符,*匹配0个或多个字符,AND,OR)等等
                    // 有一些您不希望作为操作符的必须转义处理:+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? :  /
                    //.setQuery(QueryBuilders.queryStringQuery("(book_111) OR (book_999)")) // or
                    //.setQuery(QueryBuilders.queryStringQuery("(book_111) AND (book_999)")) // AND
                    //.setQuery(QueryBuilders.queryStringQuery("(book_111) && (book_999)")) // AND与&&等价
                    //.setQuery(QueryBuilders.queryStringQuery("(book_111) & (book_999)")) // &不会短路计算
                    //.setQuery(QueryBuilders.queryStringQuery("book_1?1").field("name")) // ? 并且指定字段
                    //.setQuery(QueryBuilders.queryStringQuery("name:book_1?1 OR color:B*"))  // 在查询里指定字段
                    //.setQuery(QueryBuilders.queryStringQuery("name:book_1?1 | color:B*"))
                    //.setQuery(QueryBuilders.queryStringQuery("name:book_1?1 || color:B*"))  // OR与||等价
                    //.setQuery(QueryBuilders.queryStringQuery("price:[990 TO *]"))  // 范围查询
                    // 默认情况下操作符都是可选的,有两个特殊的->首选操作符是:+(这一项必须存在)和-(这一项必须不存在)
                    .setQuery(QueryBuilders.queryStringQuery("price:[990 TO *] -book*"))    // 不显示book*的数据
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    {"name":"法拉利LaFerrari","price":"2250.00万","postDate":"2018-12-12T08:38:09.129Z"}
    {"name":"法拉利488","price":"315.50-418.80万","postDate":"2018-12-12T08:38:09.107Z"}
    {"name":"Aventador","price":"630.00-755.94万","postDate":"2018-12-12T08:49:01.736Z","extra":"Extra Data"}
    命中:3

    16.2.5 Simple Query String Query(查询永远不会抛出异常,并丢弃查询的无效部分)

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("book")
                    // + 表示与操作
                    // | 表示或操作
                    // - 表示否定
                    // * 在关键字末尾表示前缀查询
                    // 小括号()表示优先级
                    // 这里通配符失效!!比如book_1?1或者book_1*1只会查出一条记录
                    .setQuery(QueryBuilders.simpleQueryStringQuery("book_11*")
    //                        .flags(SimpleQueryStringFlag.AND,SimpleQueryStringFlag.OR,SimpleQueryStringFlag.NOT)  // 指定启用哪些解析功能,默认全部启用ALL。SimpleQueryStringFlag
                    )
    
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    这个功能感觉有点鸡肋,不如QueryStringQuery

    执行结果:

    {"name":"book_110","price":562.7866825701938,"postDate":"2018-12-12T09:27:32.424Z"}
    {"name":"book_116","price":764.6107139750268,"postDate":"2018-12-12T09:27:32.425Z"}
    {"name":"book_119","price":612.4310597411385,"postDate":"2018-12-12T09:27:32.425Z"}
    {"name":"book_113","price":693.0418946151275,"postDate":"2018-12-12T09:27:32.425Z"}
    {"name":"book_117","price":955.1701411798869,"postDate":"2018-12-12T09:27:32.425Z"}
    {"name":"book_114","price":255.65009974873198,"postDate":"2018-12-12T09:27:32.425Z"}
    {"name":"book_118","price":915.8228473795552,"postDate":"2018-12-12T09:27:32.425Z"}
    {"name":"book_111","price":185.85669328040666,"postDate":"2018-12-12T09:27:32.424Z"}
    {"name":"book_112","price":8.035476335226166,"postDate":"2018-12-12T09:27:32.424Z"}
    {"name":"book_115","price":651.4301559069825,"postDate":"2018-12-12T09:27:32.425Z"}
    {"name":"book_11","price":365.2274741512962,"postDate":"2018-12-12T09:27:30.720Z"}
    命中:11

    16.3 Term level queries【查询通常用于数字、日期和枚举等结构化数据,而不是全文字段。或者,它们允许您在分析过程之前处理低级查询】

    造一些结构化数据

        /**
         * 准备结构化数据
         * @return
         * @throws IOException
         */
        public static TransportClient structuredData() throws IOException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            AdminClient admin = client.admin();
            IndicesAdminClient indicesAdminClient = admin.indices();   // 指数管理
            CreateIndexResponse createIndexResponse = indicesAdminClient.prepareCreate("school")
                    .setSettings(Settings.builder()
                            .put("index.number_of_shards", 1)   // 分片
                            .put("index.number_of_replicas", 1) // 副本
                    )
                    .addMapping("student", "sName", "type=text", "sAge", "type=integer",
                            "sClass", "type=keyword", "sTime", "type=date") // mapping
                    .get();
            System.out.println("创建索引:" + createIndexResponse.isAcknowledged());
            BulkProcessor bulkProcessor = BulkProcessor.builder(
                    client,
                    new BulkProcessor.Listener() {
                        @Override
                        public void beforeBulk(long executionId, BulkRequest request) {
                            // bulk 执行之前
                            System.out.println("beforeBulk-----" + request.getDescription());
                        }
    
                        @Override
                        public void afterBulk(long executionId,
                                              BulkRequest request,
                                              BulkResponse response) {
                            // bulk 执行之后
                            System.out.println("afterBulk------" + request.getDescription() + ",是否有错误:" + response.hasFailures());
                        }
    
                        @Override
                        public void afterBulk(long executionId,
                                              BulkRequest request,
                                              Throwable failure) {
                            //bulk 失败
                            System.out.println("报错-----" + request.getDescription() + "," + failure.getMessage());
                        }
                    })
                    .setBulkActions(300)  // 每300个request,bulk一次
                    .setConcurrentRequests(0)   // 设置并发请求的数量。值为0意味着只允许执行一个请求。值为1意味着在积累新的批量请求时允许执行1个并发请求。
                    .build();
            Random random = new Random();
            for (int i = 1; i <= 1000; i++){
                bulkProcessor.add(new IndexRequest("school", "student", i+"").source(jsonBuilder()
                        .startObject()
                        .field("sName", "Student_" + i)
                        .field("sAge", random.nextInt(100))
                        .field("sClass", "Class_" + (i % 20))
                        .field("sTime", new Date())
                        .endObject()));
            }
            bulkProcessor.flush();
            bulkProcessor.close();
            return client;
        }

    查看索引数据:GET /school/_search

    注意我这里面有大写字母

    查看索引信息:GET /school

    16.3.1 Term Query

    这里有很多彩蛋~

     

    正确写法:

    下面我们查询class字段

    正确写法:

     代码:

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    //.setQuery(QueryBuilders.termQuery("sName", "student_1"))    // 使用term查询类型为text的字段的时候,内容要全部小写
                    .setQuery(QueryBuilders.termQuery("sClass", "Class_2"))    // 使用term查询类型为keyword的字段的时候,内容区分大小写
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    为什么会出现上述彩蛋呢?

    类型为text,会解析其中的内容,比如 "Hey Guy",倒排索引会包括以下术语[hey,guy]

    类型为keyword,在倒排索引中会出现以下术语[Hey Guy] 

    所以,查询全文字段就用match,因为它知道如何分析,term比较傻,只知道精确值,擅长结构化的字段。

    16.3.2 TermsQuery

     多个查询关键字

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // 一个字段,多个value
                    .setQuery(QueryBuilders.termsQuery("sName","student_1","student_2"))
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    {"sName":"Student_1","sAge":28,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.666Z"}
    {"sName":"Student_2","sAge":20,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.689Z"}
    命中:2

    16.3.3 RangeQuery 范围查询

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    .setQuery(QueryBuilders.rangeQuery("sAge")
    //                        .gte(10)    // 大于等于
    //                        .gt(10)     // 大于
    //                        .lte(20)    // 小于等于
    //                        .lt(20)     // 小于
                            .from(0)
                            .to(5)
                            .includeLower(true) // 包含下限
                            .includeUpper(true) // 包含上限
                    )
    //                .setQuery(QueryBuilders.rangeQuery("sTime")
    //                        .lte("now") // 小于等于当前时间
    //                        .timeZone("-01:00"))    // 时区
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    ...省略
    {"sName":"Student_340","sAge":5,"sClass":"Class_0","sTime":"2018-12-13T08:39:57.821Z"}
    {"sName":"Student_372","sAge":1,"sClass":"Class_12","sTime":"2018-12-13T08:39:57.822Z"}
    {"sName":"Student_428","sAge":2,"sClass":"Class_8","sTime":"2018-12-13T08:39:57.823Z"}
    {"sName":"Student_432","sAge":0,"sClass":"Class_12","sTime":"2018-12-13T08:39:57.823Z"}
    命中:52

    16.3.4 ExistQuery

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    .setQuery(QueryBuilders.existsQuery("sName"))
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    ...省略
    {"sName":"Student_18","sAge":72,"sClass":"Class_18","sTime":"2018-12-13T08:39:57.690Z"}
    {"sName":"Student_19","sAge":43,"sClass":"Class_19","sTime":"2018-12-13T08:39:57.690Z"}
    {"sName":"Student_20","sAge":93,"sClass":"Class_0","sTime":"2018-12-13T08:39:57.690Z"}
    命中:1000

    全命中了,什么意思呢?

    这个方法的作用:对于某个字段,返回至少含有一个非空值的所有文档 。

    套用官方解释,比如:查询user字段,可以返回下面格式的数据【有值,空字符串,长度大于0的数组】

    然而下面这些就不行了【null,空数组,非查询字段】

    16.3.5 Prefix Query 前缀查询(顾名思义,肯定是把关键字作为前缀啦)

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    .setQuery(QueryBuilders.prefixQuery("sName", "student_19"))
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    {"sName":"Student_19","sAge":43,"sClass":"Class_19","sTime":"2018-12-13T08:39:57.690Z"}
    {"sName":"Student_190","sAge":53,"sClass":"Class_10","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_191","sAge":45,"sClass":"Class_11","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_192","sAge":2,"sClass":"Class_12","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_193","sAge":9,"sClass":"Class_13","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_194","sAge":67,"sClass":"Class_14","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_195","sAge":62,"sClass":"Class_15","sTime":"2018-12-13T08:39:57.696Z"}
    {"sName":"Student_196","sAge":77,"sClass":"Class_16","sTime":"2018-12-13T08:39:57.696Z"}
    {"sName":"Student_197","sAge":82,"sClass":"Class_17","sTime":"2018-12-13T08:39:57.696Z"}
    {"sName":"Student_198","sAge":38,"sClass":"Class_18","sTime":"2018-12-13T08:39:57.696Z"}
    {"sName":"Student_199","sAge":50,"sClass":"Class_19","sTime":"2018-12-13T08:39:57.696Z"}
    命中:11

    16.3.6 Wildcard Query

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // 支持通配符查询[?,*],不建议以通配符开头,那样会很慢
                    .setQuery(QueryBuilders.wildcardQuery("sName", "student_1?1"))
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    {"sName":"Student_101","sAge":87,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.692Z"}
    {"sName":"Student_111","sAge":98,"sClass":"Class_11","sTime":"2018-12-13T08:39:57.693Z"}
    {"sName":"Student_121","sAge":96,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.693Z"}
    {"sName":"Student_131","sAge":89,"sClass":"Class_11","sTime":"2018-12-13T08:39:57.694Z"}
    {"sName":"Student_141","sAge":90,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.694Z"}
    {"sName":"Student_151","sAge":52,"sClass":"Class_11","sTime":"2018-12-13T08:39:57.694Z"}
    {"sName":"Student_161","sAge":21,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_171","sAge":76,"sClass":"Class_11","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_181","sAge":18,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_191","sAge":45,"sClass":"Class_11","sTime":"2018-12-13T08:39:57.695Z"}
    命中:10

    16.3.7 Regexp Query

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // regexp查询的性能在很大程度上取决于所选择的正则表达式。匹配诸如.*之类的所有内容非常慢。*?+ 主要降低性能
                    .setQuery(QueryBuilders.regexpQuery("sName", "student_.*0"))
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    ...省略
    {"sName":"Student_170","sAge":14,"sClass":"Class_10","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_180","sAge":16,"sClass":"Class_0","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_190","sAge":53,"sClass":"Class_10","sTime":"2018-12-13T08:39:57.695Z"}
    {"sName":"Student_200","sAge":12,"sClass":"Class_0","sTime":"2018-12-13T08:39:57.696Z"}
    命中:100

    16.3.8 Fuzzy Query

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // 模糊查询https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#fuzziness
                    .setQuery(QueryBuilders.fuzzyQuery("sName", "student_33"))
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    ...省略
    {"sName":"Student_83","sAge":94,"sClass":"Class_3","sTime":"2018-12-13T08:39:57.692Z"}
    {"sName":"Student_93","sAge":88,"sClass":"Class_13","sTime":"2018-12-13T08:39:57.692Z"}
    {"sName":"Student_133","sAge":34,"sClass":"Class_13","sTime":"2018-12-13T08:39:57.694Z"}
    {"sName":"Student_233","sAge":90,"sClass":"Class_13","sTime":"2018-12-13T08:39:57.696Z"}
    命中:50

    16.3.9 Type Query

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    .setQuery(QueryBuilders.typeQuery("student"))
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    就是查询type下的内容..

    ...省略
    {"sName":"Student_18","sAge":72,"sClass":"Class_18","sTime":"2018-12-13T08:39:57.690Z"}
    {"sName":"Student_19","sAge":43,"sClass":"Class_19","sTime":"2018-12-13T08:39:57.690Z"}
    {"sName":"Student_20","sAge":93,"sClass":"Class_0","sTime":"2018-12-13T08:39:57.690Z"}
    命中:1000

    16.3.10 Ids Query

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // 根据多个id查询
                    .setQuery(QueryBuilders.idsQuery("student").addIds("1","111","999"))
                    .setSize(20)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println(e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

     执行结果:

    {"sName":"Student_1","sAge":28,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.666Z"}
    {"sName":"Student_111","sAge":98,"sClass":"Class_11","sTime":"2018-12-13T08:39:57.693Z"}
    {"sName":"Student_999","sAge":6,"sClass":"Class_19","sTime":"2018-12-13T08:39:58.120Z"}
    命中:3

    17. Compound queries(复合查询)

    17.1 constant_score query

     比如查询好吃的水果,提高桃子的权重

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // 通过设置boost提高查询的权重
                    .setQuery(QueryBuilders.boolQuery()
                            .should(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("sName","student_1")).boost(3.0f))
                            .should(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("sName","student_2")).boost(0.3f)))
                    .setSize(10)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    Score:3.0,Source:{"sName":"Student_1","sAge":28,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.666Z"}
    Score:0.3,Source:{"sName":"Student_2","sAge":20,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.689Z"}
    命中:2

    17.2 bool query

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // 查询上下文
                    .setQuery(QueryBuilders.boolQuery()
                            // (查询结果)必须出现在匹配的文档中,并将有助于得分
                            .must(QueryBuilders.rangeQuery("sAge").lte(30))
                            // (查询结果)不能出现在匹配的文档中,评分被忽略
                            .mustNot(QueryBuilders.termsQuery("sName","student_2","student_4"))
                            // (查询结果)应该出现在匹配的文档中。如果bool查询位于查询上下文中,并且具有must或filter子句,should查询将失效;
                            // 如果bool查询位于筛选上下文,或者既没有must也没有filter,那么至少应该有一个查询必须匹配文档以匹配bool查询
                            //.should(QueryBuilders.termQuery("sClass","Class_1"))
                            // (查询结果)必须出现在匹配的文档中,然而,与must不同的是,查询的分数将被忽略
                            .filter(QueryBuilders.rangeQuery("sAge").gte(5)))
                    .setSize(500)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    如果只有must查询,我测试查询出304条结果;加上mustNot查询,筛选出302条数据;加上should,仍然是302条数据,因为有must;不要should,加上filter筛选出256条数据。

    ...省略
    Score:1.0,Source:{"sName":"Student_992","sAge":16,"sClass":"Class_12","sTime":"2018-12-13T08:39:58.120Z"}
    Score:1.0,Source:{"sName":"Student_997","sAge":14,"sClass":"Class_17","sTime":"2018-12-13T08:39:58.120Z"}
    Score:1.0,Source:{"sName":"Student_999","sAge":6,"sClass":"Class_19","sTime":"2018-12-13T08:39:58.120Z"}
    命中:256

    下面测试筛选上下文

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    .setQuery(QueryBuilders.boolQuery()
                            .must(QueryBuilders.rangeQuery("sAge").gte(10))
                            // 筛选上下文
                            .filter(QueryBuilders.boolQuery()
                                    // (查询结果)必须出现在匹配的文档中,并将有助于得分
                                    .must(QueryBuilders.rangeQuery("sAge").lte(30))
                                    // (查询结果)不能出现在匹配的文档中,评分被忽略
                                    .mustNot(QueryBuilders.termsQuery("sName","student_2","student_4"))
                                    // (查询结果)应该出现在匹配的文档中。如果bool查询位于查询上下文中,并且具有must或filter子句,should查询将失效;
                                    // 如果bool查询位于筛选上下文,或者既没有must也没有filter,那么至少应该有一个查询必须匹配文档以匹配bool查询
                                    .should(QueryBuilders.termQuery("sClass","Class_1"))
                            ))
                    .setSize(500)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    Score:1.0,Source:{"sName":"Student_1","sAge":28,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.666Z"}
    Score:1.0,Source:{"sName":"Student_81","sAge":23,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.692Z"}
    Score:1.0,Source:{"sName":"Student_161","sAge":21,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.695Z"}
    Score:1.0,Source:{"sName":"Student_181","sAge":18,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.695Z"}
    Score:1.0,Source:{"sName":"Student_281","sAge":21,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.698Z"}
    Score:1.0,Source:{"sName":"Student_341","sAge":19,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.822Z"}
    Score:1.0,Source:{"sName":"Student_361","sAge":14,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.822Z"}
    Score:1.0,Source:{"sName":"Student_381","sAge":11,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.822Z"}
    Score:1.0,Source:{"sName":"Student_501","sAge":23,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.825Z"}
    Score:1.0,Source:{"sName":"Student_541","sAge":21,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.826Z"}
    Score:1.0,Source:{"sName":"Student_601","sAge":27,"sClass":"Class_1","sTime":"2018-12-13T08:39:58.045Z"}
    Score:1.0,Source:{"sName":"Student_901","sAge":15,"sClass":"Class_1","sTime":"2018-12-13T08:39:58.119Z"}
    命中:12

     query&filter

    17.3 dis_max query

     ...待补充

    17.4 function_score query(function_score允许您修改查询检索的文档的得分)

      ...待补充

    17.5 boosting query

        public static TransportClient queryDSL() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // 一种复合查询,分为positive子查询和negitive子查询,两者的查询结构都会返回
                    // positive子查询的score保持不变,negative子查询的值将会根据negative_boost的值做相应程度的降低。
                    .setQuery(QueryBuilders.boostingQuery(QueryBuilders.termQuery("sName","student_1"),
                            QueryBuilders.termQuery("sClass","Class_1")).negativeBoost(0.3f))
                    .setSize(500)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

     执行结果:

    Score:1.950987,Source:{"sName":"Student_1","sAge":28,"sClass":"Class_1","sTime":"2018-12-13T08:39:57.666Z"}
    命中:1

     18 Joining queries 

     18.1 嵌套查询

     ...待补充

    18.2 Has Child Query

     ...待补充

    18.3 Has Parent Query

      ...待补充

     19. Geo queries(地理查询)

    地理形状查询需要相关依赖

    <dependency>
        <groupId>org.locationtech.spatial4j</groupId>
        <artifactId>spatial4j</artifactId>
        <version>0.7</version>
    </dependency>
    
    <dependency>
        <groupId>org.locationtech.jts</groupId>
        <artifactId>jts-core</artifactId>
        <version>1.16.0</version>
        <exclusions>
            <exclusion>
                <groupId>xerces</groupId>
                <artifactId>xercesImpl</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    关于geo_point

    PUT my_index
    {
      "mappings": {
        "_doc": {
          "properties": {
            "location": {
              "type": "geo_point"
            }
          }
        }
      }
    }
    
    PUT my_index/_doc/1
    {
      "text": "Geo-point as an object",
      "location": { 
        "lat": 41.12,    // 纬度
        "lon": -71.34    // 经度
      }
    }
    
    PUT my_index/_doc/2
    {
      "text": "Geo-point as a string",
      "location": "41.12,-71.34"    // 纬度,经度
    }
    
    PUT my_index/_doc/3
    {
      "text": "Geo-point as an array",
      "location": [ -71.34, 41.12 ] // 经度,纬度
    }
    
    GET my_index/_search
    {
      "query": {
        "geo_bounding_box": { // 查询落在框中的所有点
          "location": {
            "top_left": {
              "lat": 42,
              "lon": -72
            },
            "bottom_right": {
              "lat": 40,
              "lon": -74
            }
          }
        }
      }
    }

    19.1 geo_shape查询

    查找与指定的地理形状相交、包含或不相交的地理形状的文档。

    19.2 geo_bounding_box查询

    查找落在指定矩形中的文档

    初始化数据:数据文件点击这里

        /**
         * 从文件读取地理位置
         * 地理位置选择:http://www.gpsspg.com/maps.htm
         * @return
         * @throws IOException
         */
        private static List<String> getChinaCity() throws IOException {
            List<String> list = new ArrayList<>();
            FileInputStream in = new FileInputStream("China.txt");
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String s = null;
            while ((s = reader.readLine()) != null){
                list.add(s);
            }
            System.out.println("读取【" + list.size() + "】条数据");
            reader.close();
            in.close();
            return list;
        }
    
        /**
         * 初始化地理数据
         * @return
         * @throws IOException
         */
        public static TransportClient geoPointData() throws IOException {
            List<String> list = getChinaCity();
            TransportClient client = TransportClientFactory.getInstance().getClient();
            AdminClient admin = client.admin();
            IndicesAdminClient indicesAdminClient = admin.indices();   // 指数管理
            CreateIndexResponse createIndexResponse = indicesAdminClient.prepareCreate("china_index")
                    .setSettings(Settings.builder()
                            .put("index.number_of_shards", 1)   // 分片
                            .put("index.number_of_replicas", 1) // 副本
                    )
                    .addMapping("city", "pName", "type=keyword","cName", "type=text", "location", "type=geo_point") // mapping
                    .get();
            System.out.println("创建索引:" + createIndexResponse.isAcknowledged());
            BulkProcessor bulkProcessor = BulkProcessor.builder(
                    client,
                    new BulkProcessor.Listener() {
                        @Override
                        public void beforeBulk(long executionId, BulkRequest request) {
                            // bulk 执行之前
                            System.out.println("beforeBulk-----" + request.getDescription());
                        }
    
                        @Override
                        public void afterBulk(long executionId,
                                              BulkRequest request,
                                              BulkResponse response) {
                            // bulk 执行之后
                            System.out.println("afterBulk------" + request.getDescription() + ",是否有错误:" + response.hasFailures() + ",Msg:" + response.buildFailureMessage());
                        }
    
                        @Override
                        public void afterBulk(long executionId,
                                              BulkRequest request,
                                              Throwable failure) {
                            //bulk 失败
                            System.out.println("报错-----" + request.getDescription() + "," + failure.getMessage());
                        }
                    })
                    .setBulkActions(300)  // 每300个request,bulk一次
                    .setConcurrentRequests(0)   // 设置并发请求的数量。值为0意味着只允许执行一个请求。值为1意味着在积累新的批量请求时允许执行1个并发请求。
                    .build();
            int i = 1;
            for (String s : list){
                String[] data = s.split(",");
                Double latitude,longitude;
                // [经度:-180~180;纬度:-90~90]
                latitude = Double.parseDouble(data[3]);
                longitude = Double.parseDouble(data[2]);
                bulkProcessor.add(new IndexRequest("china_index", "city", i++ +"").source(jsonBuilder()
                        .startObject()
                        .field("pName", data[0])
                        .field("cName", data[1])
                        .field("location", new GeoPoint(latitude, longitude))
                        .endObject()));
            }
            bulkProcessor.flush();
            bulkProcessor.close();
            return client;
        }

    执行之后:

    GET /china_index/_search

    .

    下面查询:

        public static TransportClient geoBoundingBoxQuery() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("china_index")
                    // top、left、bottom、right 围成一个矩形,查询这个矩形里面的位置
                    .setQuery(QueryBuilders.geoBoundingBoxQuery("location").setCorners(40.3800284025,114.8730468750,38.8568201347,118.9599609375))
                    .setSize(100)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    查询结果:

    Score:1.0,Source:{"pName":"北京市","cName":"东城区","location":{"lat":39.92855,"lon":116.41637}}
    Score:1.0,Source:{"pName":"北京市","cName":"西城区","location":{"lat":39.91231,"lon":116.36611}}
    Score:1.0,Source:{"pName":"北京市","cName":"朝阳区","location":{"lat":39.927289,"lon":116.4498}}
    Score:1.0,Source:{"pName":"北京市","cName":"丰台区","location":{"lat":39.85856,"lon":116.28616}}
    Score:1.0,Source:{"pName":"北京市","cName":"石景山区","location":{"lat":39.90569,"lon":116.22299}}
    Score:1.0,Source:{"pName":"北京市","cName":"海淀区","location":{"lat":39.95933,"lon":116.29845}}
    Score:1.0,Source:{"pName":"北京市","cName":"顺义区","location":{"lat":40.13012,"lon":116.65477}}
    Score:1.0,Source:{"pName":"北京市","cName":"通州区","location":{"lat":39.916195,"lon":116.662852}}
    Score:1.0,Source:{"pName":"北京市","cName":"大兴区","location":{"lat":39.72684,"lon":116.34159}}
    Score:1.0,Source:{"pName":"北京市","cName":"房山区","location":{"lat":39.74788,"lon":116.14294}}
    Score:1.0,Source:{"pName":"北京市","cName":"门头沟区","location":{"lat":39.94048,"lon":116.10146}}
    Score:1.0,Source:{"pName":"北京市","cName":"昌平区","location":{"lat":40.22077,"lon":116.23128}}
    Score:1.0,Source:{"pName":"北京市","cName":"平谷区","location":{"lat":40.14062,"lon":117.12141}}
    Score:1.0,Source:{"pName":"北京市","cName":"密云区","location":{"lat":40.37625,"lon":116.84317}}
    Score:1.0,Source:{"pName":"北京市","cName":"怀柔区","location":{"lat":40.316,"lon":116.63177}}
    Score:1.0,Source:{"pName":"天津市","cName":"和平区","location":{"lat":39.11712,"lon":117.2147}}
    Score:1.0,Source:{"pName":"天津市","cName":"河东区","location":{"lat":39.12827,"lon":117.25228}}
    Score:1.0,Source:{"pName":"天津市","cName":"河西区","location":{"lat":39.10954,"lon":117.22336}}
    Score:1.0,Source:{"pName":"天津市","cName":"南开区","location":{"lat":39.13815,"lon":117.15011}}
    Score:1.0,Source:{"pName":"天津市","cName":"河北区","location":{"lat":39.14784,"lon":117.19674}}
    Score:1.0,Source:{"pName":"天津市","cName":"红桥区","location":{"lat":39.16734,"lon":117.15161}}
    Score:1.0,Source:{"pName":"天津市","cName":"滨海新区","location":{"lat":39.0032,"lon":117.71071}}
    Score:1.0,Source:{"pName":"天津市","cName":"东丽区","location":{"lat":39.08652,"lon":117.31428}}
    Score:1.0,Source:{"pName":"天津市","cName":"西青区","location":{"lat":39.14111,"lon":117.00739}}
    Score:1.0,Source:{"pName":"天津市","cName":"津南区","location":{"lat":38.9375,"lon":117.3571}}
    Score:1.0,Source:{"pName":"天津市","cName":"北辰区","location":{"lat":39.22393,"lon":117.13544}}
    Score:1.0,Source:{"pName":"天津市","cName":"武清区","location":{"lat":39.38326,"lon":117.04412}}
    Score:1.0,Source:{"pName":"天津市","cName":"宝坻区","location":{"lat":39.71755,"lon":117.30983}}
    Score:1.0,Source:{"pName":"天津市","cName":"宁河区","location":{"lat":39.33091,"lon":117.82478}}
    Score:1.0,Source:{"pName":"天津市","cName":"静海区","location":{"lat":38.94737,"lon":116.97428}}
    Score:1.0,Source:{"pName":"天津市","cName":"蓟州区","location":{"lat":40.04577,"lon":117.40829}}
    Score:1.0,Source:{"pName":"天津市","cName":"天津","location":{"lat":39.13,"lon":117.2}}
    Score:1.0,Source:{"pName":"天津市","cName":"宁河","location":{"lat":39.33,"lon":117.83}}
    Score:1.0,Source:{"pName":"天津市","cName":"静海","location":{"lat":38.93,"lon":116.92}}
    Score:1.0,Source:{"pName":"天津市","cName":"蓟县","location":{"lat":40.05,"lon":117.4}}
    Score:1.0,Source:{"pName":"天津市","cName":"宝坻","location":{"lat":39.75,"lon":117.3}}
    Score:1.0,Source:{"pName":"天津市","cName":"武清","location":{"lat":39.4,"lon":117.05}}
    Score:1.0,Source:{"pName":"河北省","cName":"唐山","location":{"lat":39.63,"lon":118.02}}
    Score:1.0,Source:{"pName":"河北省","cName":"涞水","location":{"lat":39.39,"lon":115.71}}
    Score:1.0,Source:{"pName":"河北省","cName":"涿县","location":{"lat":39.48,"lon":115.98}}
    Score:1.0,Source:{"pName":"河北省","cName":"定兴","location":{"lat":39.28,"lon":115.78}}
    Score:1.0,Source:{"pName":"河北省","cName":"容城","location":{"lat":39.06,"lon":115.86}}
    Score:1.0,Source:{"pName":"河北省","cName":"安新","location":{"lat":38.92,"lon":115.92}}
    Score:1.0,Source:{"pName":"河北省","cName":"易县","location":{"lat":39.35,"lon":115.49}}
    Score:1.0,Source:{"pName":"河北省","cName":"新城","location":{"lat":39.34,"lon":115.84}}
    Score:1.0,Source:{"pName":"河北省","cName":"雄县","location":{"lat":38.98,"lon":116.1}}
    Score:1.0,Source:{"pName":"河北省","cName":"徐水","location":{"lat":39.02,"lon":115.65}}
    Score:1.0,Source:{"pName":"河北省","cName":"满城","location":{"lat":38.95,"lon":115.45}}
    Score:1.0,Source:{"pName":"河北省","cName":"涿鹿","location":{"lat":40.37,"lon":115.2}}
    Score:1.0,Source:{"pName":"河北省","cName":"迁西","location":{"lat":40.15,"lon":118.3}}
    Score:1.0,Source:{"pName":"河北省","cName":"迁安","location":{"lat":40.02,"lon":118.69}}
    Score:1.0,Source:{"pName":"河北省","cName":"卢龙","location":{"lat":39.89,"lon":118.85}}
    Score:1.0,Source:{"pName":"河北省","cName":"滦南","location":{"lat":39.49,"lon":118.67}}
    Score:1.0,Source:{"pName":"河北省","cName":"玉田","location":{"lat":39.9,"lon":117.9}}
    Score:1.0,Source:{"pName":"河北省","cName":"唐海","location":{"lat":39.31,"lon":118.54}}
    Score:1.0,Source:{"pName":"河北省","cName":"遵化","location":{"lat":40.2,"lon":117.97}}
    Score:1.0,Source:{"pName":"河北省","cName":"乐亭","location":{"lat":39.43,"lon":118.9}}
    Score:1.0,Source:{"pName":"河北省","cName":"滦县","location":{"lat":39.74,"lon":118.73}}
    Score:1.0,Source:{"pName":"河北省","cName":"丰南","location":{"lat":39.58,"lon":118.1}}
    Score:1.0,Source:{"pName":"河北省","cName":"丰润","location":{"lat":39.82,"lon":118.13}}
    Score:1.0,Source:{"pName":"河北省","cName":"廊坊","location":{"lat":39.53,"lon":116.7}}
    Score:1.0,Source:{"pName":"河北省","cName":"安次","location":{"lat":39.52,"lon":116.69}}
    Score:1.0,Source:{"pName":"河北省","cName":"三河","location":{"lat":39.97,"lon":117.06}}
    Score:1.0,Source:{"pName":"河北省","cName":"香河","location":{"lat":39.76,"lon":117.0}}
    Score:1.0,Source:{"pName":"河北省","cName":"霸县","location":{"lat":39.12,"lon":116.38}}
    Score:1.0,Source:{"pName":"河北省","cName":"固安","location":{"lat":39.44,"lon":116.29}}
    Score:1.0,Source:{"pName":"河北省","cName":"文安","location":{"lat":38.87,"lon":116.45}}
    Score:1.0,Source:{"pName":"河北省","cName":"永清","location":{"lat":39.32,"lon":116.48}}
    Score:1.0,Source:{"pName":"河北省","cName":"大厂","location":{"lat":39.98,"lon":116.98}}
    命中:69

    我通过这个网站找出两个点,用来测试数据 http://www.gpsspg.com/maps.htm

    19.3 geo_distance查询

    查找固定中心,指定半径范围内的文档

        public static TransportClient geoBoundingBoxQuery() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("china_index")
                    // top、left、bottom、right 围成一个矩形,查询这个矩形里面的位置
                    //.setQuery(QueryBuilders.geoBoundingBoxQuery("location").setCorners(40.3800284025,114.8730468750,38.8568201347,118.9599609375))
                    // 查找以北京为中心,半径为200千米范围内的城市
                    .setQuery(QueryBuilders.geoDistanceQuery("location").point(39.6056881783,116.6748046875).distance(20, DistanceUnit.KILOMETERS))
                    .setSize(100)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果:

    Score:1.0,Source:{"pName":"河北省","cName":"廊坊","location":{"lat":39.53,"lon":116.7}}
    Score:1.0,Source:{"pName":"河北省","cName":"安次","location":{"lat":39.52,"lon":116.69}}
    命中:2

    19.4 geo_polygon查询

     查找指定多边形内的文档

     我先选择一个多边形的几个点

    23.6042618471,113.0932617188

     

    22.3703963443,112.4780273438

     

    21.4530686331,113.7963867188

     

    22.8571947010,115.1147460938

     下面查询

    public static TransportClient geoPolygonQuery() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            List<GeoPoint> list = new ArrayList<>();
            list.add(new GeoPoint(23.6042618471,113.0932617188));
            list.add(new GeoPoint(22.3703963443,112.4780273438));
            list.add(new GeoPoint(21.4530686331,113.7963867188));
            list.add(new GeoPoint(22.8571947010,115.1147460938));
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("china_index")
                    // 查找多边形内的城市
                    .setQuery(QueryBuilders.geoPolygonQuery("location", list))
                    .setSize(100)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果

    Score:1.0,Source:{"pName":"广东省","cName":"广州","location":{"lat":23.12908,"lon":113.26436}}
    Score:1.0,Source:{"pName":"广东省","cName":"越秀","location":{"lat":23.12901,"lon":113.2668}}
    Score:1.0,Source:{"pName":"广东省","cName":"荔湾","location":{"lat":23.12586,"lon":113.24428}}
    Score:1.0,Source:{"pName":"广东省","cName":"海珠","location":{"lat":23.08331,"lon":113.3172}}
    Score:1.0,Source:{"pName":"广东省","cName":"天河","location":{"lat":23.12463,"lon":113.36199}}
    Score:1.0,Source:{"pName":"广东省","cName":"白云","location":{"lat":23.157032,"lon":113.273238}}
    Score:1.0,Source:{"pName":"广东省","cName":"黄埔","location":{"lat":23.18139,"lon":113.48067}}
    Score:1.0,Source:{"pName":"广东省","cName":"花都","location":{"lat":23.40391,"lon":113.22026}}
    Score:1.0,Source:{"pName":"广东省","cName":"番禺","location":{"lat":22.93772,"lon":113.38424}}
    Score:1.0,Source:{"pName":"广东省","cName":"南沙","location":{"lat":22.80169,"lon":113.52497}}
    Score:1.0,Source:{"pName":"广东省","cName":"增城","location":{"lat":23.26093,"lon":113.8109}}
    Score:1.0,Source:{"pName":"广东省","cName":"深圳","location":{"lat":22.54286,"lon":114.05956}}
    Score:1.0,Source:{"pName":"广东省","cName":"福田","location":{"lat":22.52291,"lon":114.05454}}
    Score:1.0,Source:{"pName":"广东省","cName":"罗湖","location":{"lat":22.54836,"lon":114.13166}}
    Score:1.0,Source:{"pName":"广东省","cName":"南山","location":{"lat":22.53325,"lon":113.93069}}
    Score:1.0,Source:{"pName":"广东省","cName":"盐田","location":{"lat":22.557,"lon":114.23679}}
    Score:1.0,Source:{"pName":"广东省","cName":"宝安","location":{"lat":22.55329,"lon":113.88308}}
    Score:1.0,Source:{"pName":"广东省","cName":"龙岗","location":{"lat":22.71991,"lon":114.24779}}
    Score:1.0,Source:{"pName":"广东省","cName":"龙华","location":{"lat":22.696694,"lon":114.044612}}
    Score:1.0,Source:{"pName":"广东省","cName":"坪山","location":{"lat":22.69084,"lon":114.34632}}
    Score:1.0,Source:{"pName":"广东省","cName":"珠海","location":{"lat":22.27073,"lon":113.57668}}
    Score:1.0,Source:{"pName":"广东省","cName":"香洲","location":{"lat":22.265939,"lon":113.543202}}
    Score:1.0,Source:{"pName":"广东省","cName":"斗门","location":{"lat":22.20903,"lon":113.29658}}
    Score:1.0,Source:{"pName":"广东省","cName":"金湾","location":{"lat":22.14589,"lon":113.3642}}
    Score:1.0,Source:{"pName":"广东省","cName":"佛山","location":{"lat":23.02185,"lon":113.12192}}
    Score:1.0,Source:{"pName":"广东省","cName":"禅城","location":{"lat":23.00944,"lon":113.12249}}
    Score:1.0,Source:{"pName":"广东省","cName":"高明","location":{"lat":22.90026,"lon":112.89262}}
    Score:1.0,Source:{"pName":"广东省","cName":"三水","location":{"lat":23.15585,"lon":112.89672}}
    Score:1.0,Source:{"pName":"广东省","cName":"南海","location":{"lat":23.02882,"lon":113.14278}}
    Score:1.0,Source:{"pName":"广东省","cName":"顺德","location":{"lat":22.80536,"lon":113.29321}}
    Score:1.0,Source:{"pName":"广东省","cName":"江门","location":{"lat":22.57865,"lon":113.08161}}
    Score:1.0,Source:{"pName":"广东省","cName":"江海","location":{"lat":22.56028,"lon":113.11103}}
    Score:1.0,Source:{"pName":"广东省","cName":"蓬江","location":{"lat":22.59514,"lon":113.07845}}
    Score:1.0,Source:{"pName":"广东省","cName":"新会","location":{"lat":22.45877,"lon":113.03231}}
    Score:1.0,Source:{"pName":"广东省","cName":"台山","location":{"lat":22.25156,"lon":112.7939}}
    Score:1.0,Source:{"pName":"广东省","cName":"鹤山","location":{"lat":22.7653,"lon":112.96436}}
    Score:1.0,Source:{"pName":"广东省","cName":"开平","location":{"lat":22.37638,"lon":112.69851}}
    Score:1.0,Source:{"pName":"广东省","cName":"惠州","location":{"lat":23.11075,"lon":114.41679}}
    Score:1.0,Source:{"pName":"广东省","cName":"惠城","location":{"lat":23.08383,"lon":114.38273}}
    Score:1.0,Source:{"pName":"广东省","cName":"惠阳","location":{"lat":22.78851,"lon":114.45646}}
    Score:1.0,Source:{"pName":"广东省","cName":"惠东","location":{"lat":22.98486,"lon":114.71999}}
    Score:1.0,Source:{"pName":"广东省","cName":"东莞","location":{"lat":23.02067,"lon":113.75179}}
    Score:1.0,Source:{"pName":"广东省","cName":"中山","location":{"lat":22.51595,"lon":113.3926}}
    Score:1.0,Source:{"pName":"澳门","cName":"澳门","location":{"lat":22.13,"lon":113.33}}
    Score:1.0,Source:{"pName":"香港","cName":"香港","location":{"lat":22.2,"lon":114.1}}
    命中:45

     20 脚本查询

        public static TransportClient scriptQuery() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("param1", "Class_2");
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    // inlined script
                    //.setQuery(QueryBuilders.scriptQuery(new Script("doc['sName'].value == 'Student_666'")))
                    // 带参数的
                    .setQuery(QueryBuilders.scriptQuery(new Script(ScriptType.INLINE,"painless",
                            "doc['sClass'].value == params.param1",parameters)))
                    .setSize(10)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果

    Score:1.0,Source:{"sName":"Student_2","sAge":20,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.689Z"}
    Score:1.0,Source:{"sName":"Student_22","sAge":6,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.690Z"}
    Score:1.0,Source:{"sName":"Student_42","sAge":83,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.690Z"}
    Score:1.0,Source:{"sName":"Student_62","sAge":18,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.691Z"}
    Score:1.0,Source:{"sName":"Student_82","sAge":63,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.692Z"}
    Score:1.0,Source:{"sName":"Student_102","sAge":96,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.693Z"}
    Score:1.0,Source:{"sName":"Student_122","sAge":83,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.693Z"}
    Score:1.0,Source:{"sName":"Student_142","sAge":97,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.694Z"}
    Score:1.0,Source:{"sName":"Student_162","sAge":26,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.695Z"}
    Score:1.0,Source:{"sName":"Student_182","sAge":66,"sClass":"Class_2","sTime":"2018-12-13T08:39:57.695Z"}
    命中:50

    21 Span 查询

    Span查询是低级的位置查询,提供对指定术语的顺序和接近程度的专业控制。这些通常用于实现对法律文件或专利的非常具体的查询。

        public static TransportClient spanQuery() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            SearchResponse searchResponse = client.prepareSearch()
                    .setIndices("school")
                    .setQuery(QueryBuilders.spanTermQuery("sName","student_666"))
                    .setSize(10)    // 返回数量
                    .get();
            searchResponse.getHits().forEach(e -> {
                System.out.println("Score:" + e.getScore() + ",Source:" + e.getSourceAsString());
            });
            System.out.println("命中:" + searchResponse.getHits().totalHits);
            return client;
        }

    执行结果

    Score:6.5032897,Source:{"sName":"Student_666","sAge":10,"sClass":"Class_6","sTime":"2018-12-13T08:39:58.046Z"}
    命中:1

    22 Administration

    22.1 添加索引

        public static TransportClient createIndex() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            AdminClient admin = client.admin();
            IndicesAdminClient indicesAdminClient = admin.indices();   // 指数管理
            // 创建index
            CreateIndexResponse createIndexResponse = indicesAdminClient.prepareCreate("twitter")
                    .setSettings(Settings.builder()
                            .put("index.number_of_shards", 3)   // 分片
                            .put("index.number_of_replicas", 2) // 副本
                    )
                    .addMapping("_doc", "message", "type=text") // mapping
                    .addAlias(new Alias("twitter_alias"))
                    .get();
            System.out.println(createIndexResponse.isAcknowledged());
            return client;
        }

    返回true

    22.2 查看索引信息

        public static TransportClient getIndex() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            AdminClient admin = client.admin();
            IndicesAdminClient indicesAdminClient = admin.indices();   // 指数管理
            // 获取index
            GetIndexResponse getIndexResponse = indicesAdminClient.prepareGetIndex().addIndices("twitter").get();
            getIndexResponse.getMappings().forEach(e -> {
                String key = e.key;
                ImmutableOpenMap<String, MappingMetaData> map = e.value;
                System.out.println("Index:" + key);
                map.forEach(n -> {
                    String type = n.key;
                    MappingMetaData metaData = n.value;
                    System.out.println(type + "|" + metaData.getSourceAsMap());
                });
            });
            System.out.println("**********************************");
            getIndexResponse.getAliases().forEach(e -> {
                String key = e.key;
                List<AliasMetaData> value = e.value;
                System.out.println("----" + key + "----");
                value.forEach(a -> {
                    System.out.println(a.alias());
                });
            });
            System.out.println("**********************************");
            getIndexResponse.getSettings().forEach(e -> {
                String key = e.key;
                Settings value = e.value;
                System.out.println("----" + key + "----");
                value.keySet().forEach(k -> {
                    System.out.println(k + ":" + value.get(k));
                });
            });
    
            return client;
        }

    执行结果

    Index:twitter
    _doc|{properties={message={type=text}}}
    **********************************
    ----twitter----
    twitter_alias
    **********************************
    ----twitter----
    index.creation_date:1545383477041
    index.number_of_replicas:2
    index.number_of_shards:3
    index.provided_name:twitter
    index.uuid:Zggv0JmiSGCM27S2A_D-og
    index.version.created:6050099

    22.3 删除索引

        public static TransportClient delIndex() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            AcknowledgedResponse response = client.admin().indices().prepareDelete("twitter").get();
            System.out.println(response.isAcknowledged());
            return client;
        }

    返回true

    22.4 如果你建立好索引,想要添加mapping【已经建立好的mapping字段不允许修改】

        public static TransportClient putIndexMapping() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            AdminClient admin = client.admin();
            IndicesAdminClient indicesAdminClient = admin.indices();   // 指数管理
            // 增加新的mapping
            AcknowledgedResponse response = indicesAdminClient.preparePutMapping("twitter")
                    .setType("_doc")
                    .setSource("afterAdd", "type=keyword")
                    .get();
            System.out.println(response.isAcknowledged());
            return client;
        }

    返回true

    再来看index信息(通过getIndex

    Index:twitter
    _doc|{properties={afterAdd={type=keyword}, message={type=text}}}
    **********************************
    ----twitter----
    twitter_alias
    **********************************
    ----twitter----
    index.creation_date:1545383985875
    index.number_of_replicas:2
    index.number_of_shards:3
    index.provided_name:twitter
    index.uuid:K2_5S8pIR4mqLGga7-0ZHQ
    index.version.created:6050099

     23 集群信息

        /**
         * 集群信息,节点信息,索引信息,状态信息
         * @return
         * @throws UnknownHostException
         */
        public static TransportClient clusterInfo() throws UnknownHostException {
            TransportClient client = TransportClientFactory.getInstance().getClient();
            AdminClient admin = client.admin();
            // 集群管理
            ClusterHealthResponse healths = admin.cluster().prepareHealth().get();
            String clusterName = healths.getClusterName();
            int numberOfDataNodes = healths.getNumberOfDataNodes();
            int numberOfNodes = healths.getNumberOfNodes();
            System.out.println("集群名称:" + clusterName);
            System.out.println("数据节点数:" + numberOfDataNodes);
            System.out.println("节点数:" + numberOfNodes);
            for (ClusterIndexHealth health : healths.getIndices().values()) {
                String index = health.getIndex();
                int numberOfShards = health.getNumberOfShards();
                int numberOfReplicas = health.getNumberOfReplicas();
                ClusterHealthStatus status = health.getStatus();
                System.out.println("索引:" + index + ",分片数:" + numberOfShards + ",副本数:" + numberOfReplicas + ",状态:" + status.name());
            }
    
            return client;
        }

    执行结果

    集群名称:my-elasticsearch
    数据节点数:1
    节点数:1
    索引:area,分片数:1,副本数:1,状态:YELLOW
    索引:china_index,分片数:1,副本数:1,状态:YELLOW
    索引:book,分片数:5,副本数:1,状态:YELLOW
    索引:test_ik_index,分片数:1,副本数:1,状态:YELLOW
    索引:posts,分片数:5,副本数:1,状态:YELLOW
    索引:.kibana_1,分片数:1,副本数:0,状态:GREEN
    索引:clothes,分片数:5,副本数:1,状态:YELLOW
    索引:all_books,分片数:5,副本数:1,状态:YELLOW
    索引:twitter,分片数:3,副本数:2,状态:YELLOW
    索引:it_book,分片数:5,副本数:1,状态:YELLOW
    索引:car,分片数:5,副本数:1,状态:YELLOW
    索引:school,分片数:1,副本数:1,状态:YELLOW
    索引:story,分片数:5,副本数:1,状态:YELLOW

    TransportClient到此为止,下面是ES新API--Rest Client

  • 相关阅读:
    Luogu_P3435 [POI2006]OKR-Periods of Words KMP
    NOIP2019游记
    []記錄容易出錯的地方和一些知識
    [题解]luogu_P3939_数颜色(vector二分
    [题解]luogu_P4819_杀人游戏(缩点
    [题解]NOIP2018_赛道修建(二分/树形dp/set/贪心
    [题解]luogu_P4161_(排列/lcm
    [题解]luogu_P4886_快递员(点分治
    [题解]luogu_P3523(树上覆盖
    [题解]luogu_P2466(区间dp
  • 原文地址:https://www.cnblogs.com/LUA123/p/9967638.html
Copyright © 2020-2023  润新知