• Java High Level REST Client 使用教程


    说明

      之前写过一个用jest操作es的文章,不过感觉写的有点乱。而且jest操作es的时候其实很多东西还是使用的es的一些东西。感觉还不如直接用官方的java客户端了。

    所以就研究了下high-level-client,感觉挺好用的,而且官方文档很详细。推荐使用。

      下面进入正题,写的东西大部分都是基于官方文档的。自己封装了个查询用的Criteria类,方便查询。

    elasticsearch官方文档: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html 

    Java High Level REST Client 官方文档 https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html 下面的实现大部分基于这个文档。

    es客户端谷歌插件,方便没法翻墙的同学。 ElasticSearch-Head_v0.1.4.crx https://lanzous.com/iccd9sj

    maven引用

            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>elasticsearch-rest-high-level-client</artifactId>
                <version>7.6.2</version>
            </dependency>
          <!-- 以下非必须引用,是一些辅助工具包 -->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.12</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>compile</scope>
            </dependency>

    操作

    1、主要有 模版、index的一些操作。

    2、数据操作方面有 插入、批量插入、删除、更新、根据条件更新。

    3、数据查询 按数据库查询来说有 = (TermQuery) 、<= >= (RangeQuery)、in (TermsQuery)、not in (mustNot+TermsQuery) 都封装到了Criteria类里。

    import cn.hutool.core.collection.CollUtil;
    import cn.hutool.core.date.DatePattern;
    import cn.hutool.core.date.DateUtil;
    import cn.hutool.core.lang.Console;
    import cn.hutool.core.util.RandomUtil;
    import cn.hutool.json.JSONConfig;
    import cn.hutool.json.JSONObject;
    import cn.hutool.json.JSONUtil;
    import lombok.Data;
    import org.apache.http.HttpHost;
    import org.elasticsearch.action.admin.indices.alias.Alias;
    import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
    import org.elasticsearch.action.bulk.BulkRequest;
    import org.elasticsearch.action.bulk.BulkResponse;
    import org.elasticsearch.action.delete.DeleteRequest;
    import org.elasticsearch.action.delete.DeleteResponse;
    import org.elasticsearch.action.get.*;
    import org.elasticsearch.action.index.IndexRequest;
    import org.elasticsearch.action.index.IndexResponse;
    import org.elasticsearch.action.search.SearchRequest;
    import org.elasticsearch.action.search.SearchResponse;
    import org.elasticsearch.action.support.master.AcknowledgedResponse;
    import org.elasticsearch.client.RequestOptions;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.elasticsearch.client.indices.*;
    import org.elasticsearch.common.Strings;
    import org.elasticsearch.common.settings.Settings;
    import org.elasticsearch.common.xcontent.XContentBuilder;
    import org.elasticsearch.common.xcontent.XContentFactory;
    import org.elasticsearch.common.xcontent.XContentType;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.index.reindex.BulkByScrollResponse;
    import org.elasticsearch.index.reindex.UpdateByQueryRequest;
    import org.elasticsearch.script.Script;
    import org.elasticsearch.script.ScriptType;
    import org.elasticsearch.search.SearchHit;
    import org.elasticsearch.search.SearchHits;
    import org.elasticsearch.search.builder.SearchSourceBuilder;
    import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
    import org.elasticsearch.search.sort.SortOrder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.util.Collections;
    import java.util.Date;
    import java.util.List;
    
    /**
     * @author: sun
     * @create: 2020-04-27
     **/
    public class Main {
        RestHighLevelClient client = null;
    
        @Before
        public void before() {
            client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("127.0.0.1", 9200, "http")));
        }
    
        @Test
        public void putTemplate() throws IOException {
            PutIndexTemplateRequest request = new PutIndexTemplateRequest("test_template");
            //别名,所有根据该模版创建的index 都会添加这个别名。查询时可查询别名,就可以同时查询多个名称不同的index,根据此方法可实现index每天或每月生成等逻辑。
            request.alias(new Alias("test_index"));
            request.order(10);
            //匹配哪些index。在创建index时会生效。
            request.patterns(CollUtil.newArrayList("test_index*"));
            request.settings(Settings.builder()
                    //数据插入后多久能查到,实时性要求高可以调低
                    .put("index.refresh_interval", "10s")
                    //传输日志,对数据安全性要求高的 设置 request,默认值:request
                    .put("index.translog.durability", "async")
                    .put("index.translog.sync_interval", "120s")
                    //分片数量
                    .put("index.number_of_shards", "5")
                    //副本数量
                    .put("index.number_of_replicas", "0")
                    //单次最大查询数据的数量。默认10000。不要设置太高,如果有导出需求可以根据查询条件分批次查询。
                    .put("index.max_result_window", "100000"));
            //使用官方提供的工具构建json。可以直接拼接一个json字符串,也可以使用map嵌套。
            XContentBuilder jsonMapping = XContentFactory.jsonBuilder();
            //所有数据类型 看官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/mapping-types.html#_core_datatypes
            jsonMapping.startObject().startObject("properties")
                    .startObject("testId").field("type", "long").endObject()
                    .startObject("price").field("type", "double").endObject()
                    //keyword类型不会分词存储
                    .startObject("name").field("type", "keyword").endObject()
                    //指定分词器
                    .startObject("content").field("type", "text").field("analyzer", "ik_max_word").endObject()
                    .startObject("createTime").field("type", "date").field("format", "yyyy-MM-dd HH:mm:ss").endObject()
                    .endObject().endObject();
            request.mapping(jsonMapping);
            //设置为true只强制创建,而不是更新索引模板。如果它已经存在,它将失败
            request.create(false);
            AcknowledgedResponse response = client.indices().putTemplate(request, RequestOptions.DEFAULT);
            if (response.isAcknowledged()) {
                Console.log("创建模版成功!");
            } else {
                Console.log("创建模版失败!");
            }
        }
    
        @Test
        public void getTemplate() throws IOException {
            GetIndexTemplatesRequest getIndexTemplatesRequest = new GetIndexTemplatesRequest("test*");
            GetIndexTemplatesResponse getIndexTemplatesResponse = client.indices().getIndexTemplate(getIndexTemplatesRequest, RequestOptions.DEFAULT);
            List<IndexTemplateMetaData> indexTemplates = getIndexTemplatesResponse.getIndexTemplates();
            indexTemplates.forEach(t -> {
                Console.log(t.name());
            });
        }
    
        @Test
        public void createIndex() throws IOException {
            CreateIndexRequest request = new CreateIndexRequest("test_index_tmp");
            //这里也可以针对index单独设置。不过因为我们已经设置过模版了,所以这里就不进行设置了。
            //index其实也不用单独创建,在插入数据时,如果所有不存在,会自动创建索引。
            //request.settings();
            //request.mapping();
            //request.alias()
            CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
            if (createIndexResponse.isAcknowledged()) {
                Console.log("创建index成功!");
            } else {
                Console.log("创建index失败!");
            }
        }
    
        @Test
        public void getIndex() throws IOException {
            GetIndexRequest request = new GetIndexRequest("test_index*");
            GetIndexResponse response = client.indices().get(request, RequestOptions.DEFAULT);
            String[] indices = response.getIndices();
            for (String indexName : indices) {
                Console.log("index name:{}", indexName);
            }
        }
    
        @Test
        public void delIndex() throws IOException {
            DeleteIndexRequest request = new DeleteIndexRequest("test_index*");
    //        DeleteIndexRequest request = new DeleteIndexRequest("test_index_tmp");
            AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
            if (response.isAcknowledged()) {
                Console.log("删除index成功!");
            } else {
                Console.log("删除index失败!");
            }
        }
    
        @Test
        public void insertData() throws IOException {
            //插入数据,index不存在则自动根据匹配到的template创建。index没必要每天创建一个,如果是为了灵活管理,最低建议每月一个 yyyyMM。
            IndexRequest request = new IndexRequest("test_index_" + DateUtil.format(new Date(), "yyyyMM"));
            //最好不要自定义id 会影响插入速度。
    //        request.id("id");
            TestData testData = new TestData();
            testData.setTestId(RandomUtil.randomLong(9999999999L));
            testData.setPrice(10.0D);
            testData.setName(RandomUtil.randomString(8));
            testData.setContent("");
            testData.setCreateTime(new Date());
            request.source(new JSONObject(testData, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)).toString()
                    , XContentType.JSON);
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
            Console.log(response);
        }
        @Test
        public void getById() throws IOException {
            //注意 这里查询使用的是别名。
            GetRequest request = new GetRequest("test_index", "C-54v3EB_Nn045D7VGjz");
            String[] includes = {"name","price"};
            String[] excludes = Strings.EMPTY_ARRAY;
            FetchSourceContext fetchSourceContext = new FetchSourceContext(true,includes,excludes);
            //只查询特定字段。如果需要查询所有字段则不设置该项。
            request.fetchSourceContext(fetchSourceContext);
            GetResponse response = client.get(request, RequestOptions.DEFAULT);
            Console.log(response);
            Console.log(JSONUtil.toBean(response.getSourceAsString(),TestData.class));
        }
        
        @Test
        public void delById() throws IOException {
            DeleteRequest request = new DeleteRequest("test_index", "7e5gv3EB_Nn045D7pGdA");
            DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
            Console.log(response);
        }
        @Test
        public void multiGetById() throws IOException {
            //多个根据id查询
            MultiGetRequest request = new MultiGetRequest();
            request.add("test_index","D-56v3EB_Nn045D7vmjh");
            //两种写法
            request.add(new MultiGetRequest.Item(
                    "test_index",
                    "MO57v3EB_Nn045D7aGgU"));
            MultiGetResponse response = client.mget(request, RequestOptions.DEFAULT);
            for (MultiGetItemResponse itemResponse : response) {
                Console.log(itemResponse.getResponse().getSourceAsString());
            }
        }
        
        @Test
        public void batchInsertData() throws IOException {
            //批量插入数据,更新和删除同理
            BulkRequest request = new BulkRequest("test_index_" + DateUtil.format(new Date(), "yyyyMM"));
            for (int i = 0; i < 1000; i++) {
                TestData testData = new TestData();
                testData.setTestId(RandomUtil.randomLong(9999999999L));
                testData.setPrice(100.0D);
                testData.setName(RandomUtil.randomString(8));
                testData.setContent("");
                testData.setCreateTime(new Date());
                request.add(new IndexRequest().source(new JSONObject(testData, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)).toString()
                        , XContentType.JSON));
            }
            BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
            Console.log("插入状态:{} 数量:{} ",response.status(),response.getItems().length);
        }
        @Test
        public void updateByQuery() throws IOException {
            UpdateByQueryRequest request = new UpdateByQueryRequest("test_index");
            //默认情况下,版本冲突会中止 UpdateByQueryRequest 进程,但是你可以用以下命令来代替
            //设置版本冲突继续
            request.setConflicts("proceed");
            //设置更新条件
            request.setQuery(QueryBuilders.rangeQuery("createTime").gte("2020-04-28 11:30:24").lte("2020-04-28 15:30:24"));
            //限制更新条数
            request.setMaxDocs(10);
            request.setScript(new Script(ScriptType.INLINE,"painless","ctx._source.testId=999999;", Collections.emptyMap()));
            BulkByScrollResponse response = client.updateByQuery(request, RequestOptions.DEFAULT);
            Console.log(response);
        }
        @Test
        public void query() throws IOException {
            SearchRequest request = new SearchRequest("test_index");
            SearchSourceBuilder builder = Criteria.create().addRangeQuery("createTime", "2020-04-28 11:30:24", "2020-04-28 15:30:24").builder();
            builder.from(0);
            builder.size(11);
            builder.sort("createTime", SortOrder.ASC);
            //不返回源数据。只有条数之类的数据。
    //        builder.fetchSource(false);
            request.source(builder);
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            SearchHits hits = response.getHits();
            for (SearchHit hit : hits) {
                Console.log(hit.getSourceAsString());
            }
            Console.log("总数:{}",response.getHits().getTotalHits().value);
        }
    
        @After
        public void after() throws IOException {
            client.close();
        }
    }
    
    @Data
    class TestData {
        private long testId;
        private double price;
        private String name;
        private String content;
        private Date createTime;
    }

    Criteria类

    import cn.hutool.core.util.StrUtil;
    import org.elasticsearch.index.query.BoolQueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.search.builder.SearchSourceBuilder;
    
    import java.util.List;
    
    /**
     * 复合查询封装
     */
    public class Criteria {
        private final BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        
        public static Criteria create(){
            return new Criteria();
        }
        
        /**
         * 条件增加完成后,获取需要操作的对象
         * 
         * @return
         */
        public SearchSourceBuilder builder() {
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            return searchSourceBuilder.query(boolQueryBuilder);
        }
    
        /**
         * 增加条件查询
         * 
         * @param fieldName
         * @param fieldValue
         */
        public Criteria addTermQuery(String fieldName, String fieldValue) {
            if (StrUtil.isNotBlank(fieldName) && StrUtil.isNotBlank(fieldValue)) {
                boolQueryBuilder.filter(QueryBuilders.termQuery(fieldName, fieldValue));
            }
            return this;
        }
        /**
         * 增加条件查询
         * 主要针对 内容分词后 精确匹配 fieldValue 不分词
         * @param fieldName
         * @param fieldValue
         */
        public Criteria addMatchPhraseQuery(String fieldName, String fieldValue) {
            if (StrUtil.isNotBlank(fieldName) && StrUtil.isNotBlank(fieldValue)) {
                boolQueryBuilder.filter(QueryBuilders.matchPhraseQuery(fieldName, fieldValue));
            }
            return this;
        }
    
        /**
         * 增加区间查询
         * 
         * @param fieldName
         * @param gteValue
         * @param lteValue
         */
        public Criteria addRangeQuery(String fieldName, Object gteValue, Object lteValue) {
            if (StrUtil.isNotBlank(fieldName)) {
                boolQueryBuilder.filter(QueryBuilders.rangeQuery(fieldName).gte(gteValue).lte(lteValue).includeLower(true)
                        .includeUpper(true));
            }
            return this;
        }
    
        /**
         * 增加包含查询,相当于sql中的in
         * 
         * @param fieldName
         * @param values
         */
        public Criteria addTermsQuery(String fieldName, List<?> values) {
            if (StrUtil.isNotBlank(fieldName) && values != null && values.size() > 0) {
                boolQueryBuilder.filter(QueryBuilders.termsQuery(fieldName, values));
            }
            return this;
        }
        
        /**
         * 增加不包含查询,相当于sql中的 not in
         * 
         * @param fieldName
         * @param values
         */
        public Criteria addNotTermsQuery(String fieldName, List<?> values) {
            if (StrUtil.isNotBlank(fieldName) && values != null && values.size() > 0) {
                boolQueryBuilder.mustNot(QueryBuilders.termsQuery(fieldName, values));
            }
            return this;
        }
        
    }
  • 相关阅读:
    POJ3253Fence Repair(优先队列或单调队列)
    POJ3630Phone List(字典树)
    HDU1896Stones(优先队列)
    POJ3468 A Simple Problem with Integers(线段树延时标记)
    HDU3535AreYouBusy(分组背包)
    C++ 学习涨姿势汇总
    [C++] std::vector 使用
    Cocos2dx-3.2 引擎学习(四)之CCScheduler
    Cocos2dx-3.2 引擎学习(三)之AssetsManager
    Cocos2dx-3.2 引擎学习(二)之Director
  • 原文地址:https://www.cnblogs.com/enenen/p/12841534.html
Copyright © 2020-2023  润新知