• Elastic Stack--10--QueryBuilders UpdateQuery


    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

    文章目录


    QueryBuilders

    package com.elasticsearch;
    import org.elasticsearch.action.ActionListener;
    import org.elasticsearch.action.search.SearchResponse;
    import org.elasticsearch.index.query.IndicesQueryBuilder;
    import org.elasticsearch.index.query.QueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    /**
     * Created by lw on 14-7-15.
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * elasticsearch以提供了一个完整的Java查询dsl其余查询dsl。
     * QueryBuilders工厂构建
     * API:
     * http://www.elasticsearch.org/guide/en/elasticsearch/client/java-api/current/query-dsl-queries.html
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    public class Es_QueryBuilders_DSL {
     
        /**
         * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         * match query 单个匹配
         * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         */
        protected static QueryBuilder matchQuery() {
            return QueryBuilders.matchQuery("name", "葫芦4032娃");
        }
     
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * multimatch  query
     * 创建一个匹配查询的布尔型提供字段名称和文本。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder multiMatchQuery() {
        //现住址和家乡在【山西省太原市7429街道】的人
        return QueryBuilders.multiMatchQuery(
                "山西省太原市7429街道",     // Text you are looking for
                "home", "now_home"       // Fields you query on
        );
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * boolean query and 条件组合查询
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder booleanQuery() {
    
        return QueryBuilders
                .boolQuery()
                .must(QueryBuilders.termQuery("name", "葫芦3033娃"))
                .must(QueryBuilders.termQuery("home", "山西省太原市7967街道"))
                .mustNot(QueryBuilders.termQuery("isRealMen", false))
                .should(QueryBuilders.termQuery("now_home", "山西省太原市"));
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * ids query
     * 构造一个只会匹配的特定数据 id 的查询。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder idsQuery() {
        return QueryBuilders.idsQuery().ids("CHszwWRURyK08j01p0Mmug", "ojGrYKMEQCCPvh75lHJm3A");
    }
    
    /**
     * TODO NotSolved
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * constant score query
     * 另一个查询和查询,包裹查询只返回一个常数分数等于提高每个文档的查询。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder constantScoreQuery() {
        /*return // Using with Filters
                QueryBuilders.constantScoreQuery(FilterBuilders.termFilter("name", "kimchy"))
                        .boost(2.0f);*/
    
        // With Queries
        return QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("name", "葫芦3033娃"))
                .boost(2.0f);
    }
    
    /**
     * TODO NotSolved
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * disjunction max query
     * 一个生成的子查询文件产生的联合查询,
     * 而且每个分数的文件具有最高得分文件的任何子查询产生的,
     * 再加上打破平手的增加任何额外的匹配的子查询。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder disMaxQuery() {
        return QueryBuilders.disMaxQuery()
                .add(QueryBuilders.termQuery("name", "kimchy"))          // Your queries
                .add(QueryBuilders.termQuery("name", "elasticsearch"))   // Your queries
                .boost(1.2f)
                .tieBreaker(0.7f);
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * fuzzy query
     * 使用模糊查询匹配文档查询。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder fuzzyQuery() {
        return QueryBuilders.fuzzyQuery("name", "葫芦3582");
    }
    
    /**
     * TODO NotSolved
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * has child / has parent
     * 父或者子的文档查询
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder hasChildQuery() {
        return // Has Child
                QueryBuilders.hasChildQuery("blog_tag",
                        QueryBuilders.termQuery("tag", "something"));
    
        // Has Parent
        /*return QueryBuilders.hasParentQuery("blog",
                QueryBuilders.termQuery("tag","something"));*/
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * matchall query
     * 查询匹配所有文件。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder matchAllQuery() {
        return QueryBuilders.matchAllQuery();
    }
    
    /**
     * TODO NotSolved
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * more like this (field) query (mlt and mlt_field)
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder moreLikeThisQuery() {
        // mlt Query
        QueryBuilders.moreLikeThisQuery("home", "now_home") // Fields
                .likeText("山西省太原市7429街道")                 // Text
                .minTermFreq(1)                                 // Ignore Threshold
                .maxQueryTerms(12);                             // Max num of Terms
        // in generated queries
    
        // mlt_field Query
        return QueryBuilders.moreLikeThisFieldQuery("home")              // Only on single field
                .likeText("山西省太原市7429街道")
                .minTermFreq(1)
                .maxQueryTerms(12);
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * prefix query
     * 包含与查询相匹配的文档指定的前缀。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder prefixQuery() {
        return QueryBuilders.prefixQuery("name", "葫芦31");
    }
    
    /**
     * TODO NotSolved
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * querystring query
     *   查询解析查询字符串,并运行它。有两种模式,这种经营。
     * 第一,当没有添加字段(使用{ @link QueryStringQueryBuilder #字段(String)},将运行查询一次,非字段前缀
     *   将使用{ @link QueryStringQueryBuilder # defaultField(字符串)}。
     * 第二,当一个或多个字段
     *   (使用{ @link QueryStringQueryBuilder #字段(字符串)}),将运行提供的解析查询字段,并结合
     *   他们使用DisMax或者一个普通的布尔查询(参见{ @link QueryStringQueryBuilder # useDisMax(布尔)})。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder queryString() {
        return QueryBuilders.queryString("+kimchy -elasticsearch");
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * range query
     * 查询相匹配的文档在一个范围。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder rangeQuery() {
        return QueryBuilders
                .rangeQuery("name")
                .from("葫芦1000娃")
                .to("葫芦3000娃")
                .includeLower(true)     //包括下界
                .includeUpper(false); //包括上界
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * span queries (first, near, not, or, term)
     * 跨度查询
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder spanQueries() {
        // Span First
        QueryBuilders.spanFirstQuery(
                QueryBuilders.spanTermQuery("name", "葫芦580娃"),  // Query
                                            // Max查询范围的结束位置
        );
    
        // Span Near TODO NotSolved
        QueryBuilders.spanNearQuery()
                .clause(QueryBuilders.spanTermQuery("name", "葫芦580娃")) // Span Term Queries
                .clause(QueryBuilders.spanTermQuery("name", "葫芦3812娃"))
                .clause(QueryBuilders.spanTermQuery("name", "葫芦7139娃"))
                .slop(30000)                                               // Slop factor
                .inOrder(false)
                .collectPayloads(false);
    
        // Span Not TODO NotSolved
        QueryBuilders.spanNotQuery()
                .include(QueryBuilders.spanTermQuery("name", "葫芦580娃"))
                .exclude(QueryBuilders.spanTermQuery("home", "山西省太原市2552街道"));
    
        // Span Or TODO NotSolved
        return QueryBuilders.spanOrQuery()
                .clause(QueryBuilders.spanTermQuery("name", "葫芦580娃"))
                .clause(QueryBuilders.spanTermQuery("name", "葫芦3812娃"))
                .clause(QueryBuilders.spanTermQuery("name", "葫芦7139娃"));
    
        // Span Term
        //return QueryBuilders.spanTermQuery("name", "葫芦580娃");
    }
    
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * term query
     * 一个查询相匹配的文件包含一个术语。。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder termQuery() {
        return QueryBuilders.termQuery("name", "葫芦580娃");
    }
    
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * terms query
     * 一个查询相匹配的多个value
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder termsQuery() {
        return QueryBuilders.termsQuery("name", // field
                "葫芦580娃", "葫芦3812娃")                 // values
                .minimumMatch(1);               // 设置最小数量的匹配提供了条件。默认为1。
    }
    
    /**
     * TODO NotSolved
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * top children  query
     * 构建了一种新的评分的子查询,与子类型和运行在子文档查询。这个查询的结果是,那些子父文档文件匹配。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder topChildrenQuery() {
        return QueryBuilders.topChildrenQuery(
                "blog_tag",                                 // field
                QueryBuilders.termQuery("name", "葫芦3812娃") // Query
        )
                .score("max")                               // max, sum or avg
                .factor(5)
                .incrementalFactor(2);
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * wildcard query
     *   实现了通配符搜索查询。支持通配符* < /tt>,
     *   匹配任何字符序列(包括空), ? < /tt>,
     *   匹配任何单个的字符。注意该查询可以缓慢,因为它
     *   许多方面需要遍历。为了防止WildcardQueries极其缓慢。
     *   一个通配符词不应该从一个通配符* < /tt>或
     *   < /tt>  ?。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder wildcardQuery() {
        return QueryBuilders.wildcardQuery("name", "葫芦*2娃");
    }
    
    /**
     * TODO NotSolved
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * nested query
     * 嵌套查询
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder nestedQuery() {
        return QueryBuilders.nestedQuery("location",               // Path
                QueryBuilders.boolQuery()                      // Your query
                        .must(QueryBuilders.matchQuery("location.lat", 0.962590433140581))
                        .must(QueryBuilders.rangeQuery("location.lon").lt(0.00000000000000000003))
        )
                .scoreMode("total");                  // max, total, avg or none
    }
    
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * indices query
     * 索引查询
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static IndicesQueryBuilder indicesQuery() {
        // Using another query when no match for the main one
        QueryBuilders.indicesQuery(
                QueryBuilders.termQuery("name", "葫芦3812娃"),
                Es_Utils.INDEX_DEMO_01, "index2"
        )       //设置查询索引上执行时使用不匹配指数
                .noMatchQuery(QueryBuilders.termQuery("age", "葫芦3812娃"));
    
    
        // Using all (match all) or none (match no documents)
        return QueryBuilders.indicesQuery(
                QueryBuilders.termQuery("name", "葫芦3812娃"),
                Es_Utils.INDEX_DEMO_01, "index2"
        )      // 设置不匹配查询,可以是 all 或者 none
                .noMatchQuery("none");
    }
    
    
    
    
    public static void main(String[] args) {
        Es_Utils.startupClient();
        try {
            searchTest(indicesQuery());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Es_Utils.shutDownClient();
        }
    }
    
    private static void searchTest(QueryBuilder queryBuilder) {
        //预准备执行搜索
        Es_Utils.client.prepareSearch(Es_Utils.INDEX_DEMO_01)
                .setTypes(Es_Utils.INDEX_DEMO_01_MAPPING)
                .setQuery(queryBuilder)
                .setFrom(0).setSize(20).setExplain(true)
                .execute()
                        //注册监听事件
                .addListener(new ActionListener<SearchResponse>() {
                    @Override
                    public void onResponse(SearchResponse searchResponse) {
                        Es_Utils.writeSearchResponse(searchResponse);
                    }
    
                    @Override
                    public void onFailure(Throwable e) {
    
                    }
                });
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366

    ESUtil

    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    import com.baomidou.mybatisplus.core.toolkit.StringUtils;
    import com.github.pagehelper.PageInfo;
    import com.msb.es.dto.Document;
    import com.msb.es.dto.EsDataId;
    import com.msb.es.dto.enums.FieldType;
    import lombok.extern.slf4j.Slf4j;
    import org.elasticsearch.action.ActionListener;
    import org.elasticsearch.action.DocWriteResponse;
    import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
    import org.elasticsearch.action.bulk.BulkItemResponse;
    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.GetRequest;
    import org.elasticsearch.action.get.GetResponse;
    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.search.SearchType;
    import org.elasticsearch.action.support.IndicesOptions;
    import org.elasticsearch.action.support.master.AcknowledgedResponse;
    import org.elasticsearch.action.support.replication.ReplicationResponse;
    import org.elasticsearch.action.update.UpdateRequest;
    import org.elasticsearch.action.update.UpdateResponse;
    import org.elasticsearch.client.RequestOptions;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.elasticsearch.client.indices.CreateIndexRequest;
    import org.elasticsearch.client.indices.CreateIndexResponse;
    import org.elasticsearch.client.indices.GetIndexRequest;
    import org.elasticsearch.client.indices.PutMappingRequest;
    import org.elasticsearch.common.Strings;
    import org.elasticsearch.common.settings.Settings;
    import org.elasticsearch.common.text.Text;
    import org.elasticsearch.common.unit.TimeValue;
    import org.elasticsearch.common.xcontent.XContentBuilder;
    import org.elasticsearch.common.xcontent.XContentFactory;
    import org.elasticsearch.common.xcontent.XContentType;
    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.fetch.subphase.highlight.HighlightBuilder;
    import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
    import org.elasticsearch.search.sort.SortOrder;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    import java.io.IOException;
    import java.lang.reflect.Field;
    import java.util.*;
    
    @Slf4j
    @Component
    public class ESUtil {
        @Resource
        private RestHighLevelClient restHighLevelClient;
    
        private static int index_number_of_shards = 3;//默认分片数
    
        private static int index_number_of_replicas = 1;//默认副本数  单节点
    
        public void setIndexNumber(int index_number_of_shards, int index_number_of_replicas) {
            this.index_number_of_shards = index_number_of_shards;
            this.index_number_of_replicas = index_number_of_replicas;
        }
    
        public RestHighLevelClient getInstance() {
            return restHighLevelClient;
        }
    
        //region 创建索引(默认分片数为3和副本数为1)
        /**
         * 创建索引(默认分片数为1和副本数为0)
         *
         * @param clazz 根据实体自动映射es索引
         * @throws IOException
         */
        public boolean createIndex(Class clazz) throws Exception {
            Document declaredAnnotation = (Document) clazz.getDeclaredAnnotation(Document.class);
            if (declaredAnnotation == null) {
                throw new Exception(String.format("class name: %s can not find Annotation [Document], please check", clazz.getName()));
            }
            String indexName = declaredAnnotation.indexName();
            boolean flag = createRootIndex(indexName, clazz);
            if (flag) {
                return true;
            }
            return false;
        }
    
        /**
         * 创建索引(默认分片数为5和副本数为1)
         *
         * @param clazz 根据实体自动映射es索引
         * @throws IOException
         */
        public boolean createIndexIfNotExist(Class clazz) throws Exception {
            Document declaredAnnotation = (Document) clazz.getDeclaredAnnotation(Document.class);
            if (declaredAnnotation == null) {
                throw new Exception(String.format("class name: %s can not find Annotation [Document], please check", clazz.getName()));
            }
            String indexName = declaredAnnotation.indexName();
    
            boolean indexExists = isIndexExists(indexName);
            if (!indexExists) {
                boolean flag = createRootIndex(indexName, clazz);
                if (flag) {
                    return true;
                }
            }
            return false;
        }
    
        private boolean createRootIndex(String indexName, Class clazz) throws IOException {
            CreateIndexRequest request = new CreateIndexRequest(indexName);
            request.settings(Settings.builder()
                    // 设置分片数, 副本数
                    .put("index.number_of_shards", index_number_of_shards)
                    .put("index.number_of_replicas", index_number_of_replicas)
            );
            request.mapping(generateBuilder(clazz));
            CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
            // 指示是否所有节点都已确认请求
            boolean acknowledged = response.isAcknowledged();
            // 指示是否在超时之前为索引中的每个分片启动了必需的分片副本数
            boolean shardsAcknowledged = response.isShardsAcknowledged();
            return acknowledged || shardsAcknowledged;
        }
        //endregion
    
        //region 更新索引
        /**
         * 更新索引(默认分片数为5和副本数为1):
         * 只能给索引上添加一些不存在的字段
         * 已经存在的映射不能改
         *
         * @param clazz 根据实体自动映射es索引
         * @throws IOException
         */
        public boolean updateIndex(Class clazz) throws Exception {
            Document declaredAnnotation = (Document) clazz.getDeclaredAnnotation(Document.class);
            if (declaredAnnotation == null) {
                throw new Exception(String.format("class name: %s can not find Annotation [Document], please check", clazz.getName()));
            }
            String indexName = declaredAnnotation.indexName();
            PutMappingRequest request = new PutMappingRequest(indexName);
    
            request.source(generateBuilder(clazz));
            AcknowledgedResponse response = restHighLevelClient.indices().putMapping(request, RequestOptions.DEFAULT);
            // 指示是否所有节点都已确认请求
            boolean acknowledged = response.isAcknowledged();
    
            if (acknowledged) {
                return true;
            }
            return false;
        }
        //endregion
    
        //region 删除索引
        /**
         * 删除索引
         *
         * @param indexName
         * @return
         */
        public boolean delIndex(String indexName) {
            boolean acknowledged = false;
            try {
                DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
                deleteIndexRequest.indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN);
                AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
                acknowledged = delete.isAcknowledged();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return acknowledged;
        }
        //endregion
    
        //region 判断索引是否存在
        /**
         * 判断索引是否存在
         *
         * @param indexName
         * @return
         */
        public boolean isIndexExists(String indexName) {
            boolean exists = false;
            try {
                GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
                getIndexRequest.humanReadable(true);
                exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return exists;
        }
        //endregion
    
        //region 添加单条数据
        /**
         * 添加单条数据
         * 提供多种方式:
         * 1. json
         * 2. map
         * Map jsonMap = new HashMap<>();
         * jsonMap.put("user", "kimchy");
         * jsonMap.put("postDate", new Date());
         * jsonMap.put("message", "trying out Elasticsearch");
         * IndexRequest indexRequest = new IndexRequest("posts")
         * .id("1").source(jsonMap);
         * 3. builder
         * XContentBuilder builder = XContentFactory.jsonBuilder();
         * builder.startObject();
         * {
         * builder.field("user", "kimchy");
         * builder.timeField("postDate", new Date());
         * builder.field("message", "trying out Elasticsearch");
         * }
         * builder.endObject();
         * IndexRequest indexRequest = new IndexRequest("posts")
         * .id("1").source(builder);
         * 4. source:
         * IndexRequest indexRequest = new IndexRequest("posts")
         * .id("1")
         * .source("user", "kimchy",
         * "postDate", new Date(),
         * "message", "trying out Elasticsearch");
         * 

    * 报错: Validation Failed: 1: type is missing; * 加入两个jar包解决 *

    * 提供新增或修改的功能 * * @return */ public IndexResponse index(Object o) throws Exception { Document declaredAnnotation = (Document) o.getClass().getDeclaredAnnotation(Document.class); if (declaredAnnotation == null) { throw new Exception(String.format("class name: %s can not find Annotation [Document], please check", o.getClass().getName())); } String indexName = declaredAnnotation.indexName(); IndexRequest request = new IndexRequest(indexName); Field fieldByAnnotation = getFieldByAnnotation(o, EsDataId.class); if (fieldByAnnotation != null) { fieldByAnnotation.setAccessible(true); try { Object id = fieldByAnnotation.get(o); request = request.id(id.toString()); } catch (IllegalAccessException e) { } } String userJson = JSON.toJSONString(o); request.source(userJson, XContentType.JSON); IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT); return indexResponse; } //endregion //region queryById /** * 根据id查询 * * @return */ public String queryById(String indexName, String id) throws IOException { GetRequest getRequest = new GetRequest(indexName, id); // getRequest.fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE); GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT); String jsonStr = getResponse.getSourceAsString(); return jsonStr; } //endregion //region 查询封装返回json字符串 /** * 查询封装返回json字符串 * * @param indexName * @param searchSourceBuilder * @return * @throws IOException */ public String search(String indexName, SearchSourceBuilder searchSourceBuilder) throws IOException { SearchRequest searchRequest = new SearchRequest(indexName); searchRequest.source(searchSourceBuilder); searchRequest.scroll(TimeValue.timeValueMinutes(1L)); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); String scrollId = searchResponse.getScrollId(); SearchHits hits = searchResponse.getHits(); JSONArray jsonArray = new JSONArray(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString(); JSONObject jsonObject = JSON.parseObject(sourceAsString); jsonArray.add(jsonObject); } return jsonArray.toJSONString(); } //endregion //region 查询封装,带分页 /** * 查询封装,带分页 * * @param searchSourceBuilder * @param pageNum * @param pageSize * @param s * @param * @return * @throws IOException */ public <T> PageInfo<T> search(SearchSourceBuilder searchSourceBuilder, int pageNum, int pageSize, Class<T> s) throws Exception { Document declaredAnnotation = (Document) s.getDeclaredAnnotation(Document.class); if (declaredAnnotation == null) { throw new Exception(String.format("class name: %s can not find Annotation [Document], please check", s.getName())); } String indexName = declaredAnnotation.indexName(); SearchRequest searchRequest = new SearchRequest(indexName); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); JSONArray jsonArray = new JSONArray(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString(); JSONObject jsonObject = JSON.parseObject(sourceAsString); jsonArray.add(jsonObject); } int total = (int) hits.getTotalHits().value; // 封装分页 List<T> list = jsonArray.toJavaList(s); PageInfo<T> page = new PageInfo<>(); page.setList(list); page.setPageNum(pageNum); page.setPageSize(pageSize); page.setTotal(total); page.setPages(total == 0 ? 0 : (total % pageSize == 0 ? total / pageSize : (total / pageSize) + 1)); page.setHasNextPage(page.getPageNum() < page.getPages()); return page; } //endregion //region 查询封装,返回集合 /** * 查询封装,返回集合 * * @param searchSourceBuilder * @param s * @param * @return * @throws IOException */ public <T> List<T> search(SearchSourceBuilder searchSourceBuilder, Class<T> s) throws Exception { Document declaredAnnotation = s.getDeclaredAnnotation(Document.class); if (declaredAnnotation == null) { throw new Exception(String.format("class name: %s can not find Annotation [Document], please check", s.getName())); } String indexName = declaredAnnotation.indexName(); SearchRequest searchRequest = new SearchRequest(indexName); searchRequest.source(searchSourceBuilder); searchRequest.scroll(TimeValue.timeValueMinutes(1L)); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); // //配置标题高亮显示 // HighlightBuilder highlightBuilder = new HighlightBuilder(); //生成高亮查询器 // highlightBuilder.field(title); //高亮查询字段 // highlightBuilder.field(content); //高亮查询字段 // highlightBuilder.requireFieldMatch(false); //如果要多个字段高亮,这项要为false // highlightBuilder.preTags(""); //高亮设置 // highlightBuilder.postTags(""); // // //下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等 // highlightBuilder.fragmentSize(800000); //最大高亮分片数 // highlightBuilder.numOfFragments(0); //从第一个分片获取高亮片段 String scrollId = searchResponse.getScrollId(); SearchHits hits = searchResponse.getHits(); JSONArray jsonArray = new JSONArray(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString(); JSONObject jsonObject = JSON.parseObject(sourceAsString); jsonArray.add(jsonObject); } // 封装分页 List<T> list = jsonArray.toJavaList(s); return list; } //endregion //region 批量插入文档 /** * 批量插入文档 * 文档存在 则插入 * 文档不存在 则更新 * * @param list * @return */ public <T> boolean batchSaveOrUpdate(List<T> list, boolean izAsync) throws Exception { Object o1 = list.get(0); Document declaredAnnotation = (Document) o1.getClass().getDeclaredAnnotation(Document.class); if (declaredAnnotation == null) { throw new Exception(String.format("class name: %s can not find Annotation [@Document], please check", o1.getClass().getName())); } String indexName = declaredAnnotation.indexName(); BulkRequest request = new BulkRequest(indexName); for (Object o : list) { String jsonStr = JSON.toJSONString(o); IndexRequest indexReq = new IndexRequest().source(jsonStr, XContentType.JSON); Field fieldByAnnotation = getFieldByAnnotation(o, EsDataId.class); if (fieldByAnnotation != null) { fieldByAnnotation.setAccessible(true); try { Object id = fieldByAnnotation.get(o); indexReq = indexReq.id(id.toString()); } catch (IllegalAccessException e) { } } request.add(indexReq); } if (izAsync) { BulkResponse bulkResponse = restHighLevelClient.bulk(request, RequestOptions.DEFAULT); return outResult(bulkResponse); } else { restHighLevelClient.bulkAsync(request, RequestOptions.DEFAULT, new ActionListener<BulkResponse>() { @Override public void onResponse(BulkResponse bulkResponse) { outResult(bulkResponse); } @Override public void onFailure(Exception e) { } }); } return true; } //endregion //region 删除文档 /** * 删除文档 * * @param indexName: 索引名称 * @param docId: 文档id */ public boolean deleteDoc(String indexName, String docId) throws IOException { DeleteRequest request = new DeleteRequest(indexName, docId); DeleteResponse deleteResponse = restHighLevelClient.delete(request, RequestOptions.DEFAULT); // 解析response String index = deleteResponse.getIndex(); String id = deleteResponse.getId(); long version = deleteResponse.getVersion(); ReplicationResponse.ShardInfo shardInfo = deleteResponse.getShardInfo(); if (shardInfo.getFailed() > 0) { for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) { String reason = failure.reason(); } } return true; } //endregion //region 根据json类型更新文档 /** * 根据json类型更新文档 * * @param indexName * @param docId * @param o * @return * @throws IOException */ public boolean updateDoc(String indexName, String docId, Object o) throws IOException { UpdateRequest request = new UpdateRequest(indexName, docId); request.doc(JSON.toJSONString(o), XContentType.JSON); UpdateResponse updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT); String index = updateResponse.getIndex(); String id = updateResponse.getId(); long version = updateResponse.getVersion(); if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) { return true; } else if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) { return true; } else if (updateResponse.getResult() == DocWriteResponse.Result.DELETED) { } else if (updateResponse.getResult() == DocWriteResponse.Result.NOOP) { } return false; } //endregion //region 根据Map类型更新文档 /** * 根据Map类型更新文档 * * @param indexName * @param docId * @param map * @return * @throws IOException */ public boolean updateDoc(String indexName, String docId, Map<String, Object> map) throws IOException { UpdateRequest request = new UpdateRequest(indexName, docId); request.doc(map); UpdateResponse updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT); String index = updateResponse.getIndex(); String id = updateResponse.getId(); long version = updateResponse.getVersion(); if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) { return true; } else if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) { return true; } else if (updateResponse.getResult() == DocWriteResponse.Result.DELETED) { } else if (updateResponse.getResult() == DocWriteResponse.Result.NOOP) { } return false; } //endregion //region generateBuilder public XContentBuilder generateBuilder(Class clazz) throws IOException { // 获取索引名称及类型 Document doc = (Document) clazz.getAnnotation(Document.class); System.out.println(doc.indexName()); XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); builder.startObject("properties"); Field[] declaredFields = clazz.getDeclaredFields(); for (Field f : declaredFields) { if (f.isAnnotationPresent(com.msb.es.dto.Field.class)) { // 获取注解 com.msb.es.dto.Field declaredAnnotation = f.getDeclaredAnnotation(com.msb.es.dto.Field.class); // 如果嵌套对象: /** * { * "mappings": { * "properties": { * "region": { * "type": "keyword" * }, * "manager": { * "properties": { * "age": { "type": "integer" }, * "name": { * "properties": { * "first": { "type": "text" }, * "last": { "type": "text" } * } * } * } * } * } * } * } */ if (declaredAnnotation.type() == FieldType.OBJECT) { // 获取当前类的对象-- Action Class<?> type = f.getType(); Field[] df2 = type.getDeclaredFields(); builder.startObject(f.getName()); builder.startObject("properties"); // 遍历该对象中的所有属性 for (Field f2 : df2) { if (f2.isAnnotationPresent(com.msb.es.dto.Field.class)) { // 获取注解 com.msb.es.dto.Field declaredAnnotation2 = f2.getDeclaredAnnotation(com.msb.es.dto.Field.class); builder.startObject(f2.getName()); builder.field("type", declaredAnnotation2.type().getType()); // keyword不需要分词 if (declaredAnnotation2.type() == FieldType.TEXT) { builder.field("analyzer", declaredAnnotation2.analyzer().getType()); } if (declaredAnnotation2.type() == FieldType.DATE) { builder.field("format", "yyyy-MM-dd HH:mm:ss"); } builder.endObject(); } } builder.endObject(); builder.endObject(); } else { builder.startObject(f.getName()); builder.field("type", declaredAnnotation.type().getType()); // keyword不需要分词 if (declaredAnnotation.type() == FieldType.TEXT) { builder.field("analyzer", declaredAnnotation.analyzer().getType()); } if (declaredAnnotation.type() == FieldType.DATE) { builder.field("format", "yyyy-MM-dd HH:mm:ss"); } builder.endObject(); } } } // 对应property builder.endObject(); builder.endObject(); return builder; } //endregion //region getFieldByAnnotation public static Field getFieldByAnnotation(Object o, Class annotationClass) { Field[] declaredFields = o.getClass().getDeclaredFields(); if (declaredFields != null && declaredFields.length > 0) { for (Field f : declaredFields) { if (f.isAnnotationPresent(annotationClass)) { return f; } } } return null; } //endregion //region getLowLevelClient /** * getLowLevelClient * * @return */ public RestClient getLowLevelClient() { return restHighLevelClient.getLowLevelClient(); } //endregion //region 高亮结果集 特殊处理 /** * 高亮结果集 特殊处理 * map转对象 JSONObject.parseObject(JSONObject.toJSONString(map), Content.class) * * @param searchResponse * @param highlightField */ public List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) { //解析结果 ArrayList<Map<String, Object>> list = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { Map<String, HighlightField> high = hit.getHighlightFields(); HighlightField title = high.get(highlightField); hit.getSourceAsMap().put("id", hit.getId()); Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果 //解析高亮字段,将原来的字段换为高亮字段 if (title != null) { Text[] texts = title.fragments(); String nTitle = ""; for (Text text : texts) { nTitle += text; } //替换 sourceAsMap.put(highlightField, nTitle); } list.add(sourceAsMap); } return list; } //endregion //region 查询并分页 /** * 查询并分页 * * @param index 索引名称 * @param query 查询条件 * @param size 文档大小限制 * @param from 从第几页开始 * @param fields 需要显示的字段,逗号分隔(缺省为全部字段) * @param sortField 排序字段 * @param highlightField 高亮字段 * @return */ public List<Map<String, Object>> searchListData(String index, SearchSourceBuilder query, Integer size, Integer from, String fields, String sortField, String highlightField) throws IOException { SearchRequest request = new SearchRequest(index); SearchSourceBuilder builder = query; if (StringUtils.isNotEmpty(fields)) { //只查询特定字段。如果需要查询所有字段则不设置该项。 builder.fetchSource(new FetchSourceContext(true, fields.split(","), Strings.EMPTY_ARRAY)); } from = from <= 0 ? 0 : from * size; //设置确定结果要从哪个索引开始搜索的from选项,默认为0 builder.from(from); builder.size(size); if (StringUtils.isNotEmpty(sortField)) { //排序字段,注意如果proposal_no是text类型会默认带有keyword性质,需要拼接.keyword builder.sort(sortField + ".keyword", SortOrder.ASC); } //高亮 HighlightBuilder highlight = new HighlightBuilder(); highlight.field(highlightField); //关闭多个高亮 highlight.requireFieldMatch(false); highlight.preTags(""); highlight.postTags(""); builder.highlighter(highlight); //不返回源数据。只有条数之类的数据。 //builder.fetchSource(false); request.source(builder); SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT); if (response.status().getStatus() == 200) { // 解析对象 return setSearchResponse(response, highlightField); } return null; } //endregion private boolean outResult(BulkResponse bulkResponse) { for (BulkItemResponse bulkItemResponse : bulkResponse) { DocWriteResponse itemResponse = bulkItemResponse.getResponse(); IndexResponse indexResponse = (IndexResponse) itemResponse; if (bulkItemResponse.isFailed()) { return false; } } return true; } }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648
    • 649
    • 650
    • 651
    • 652
    • 653
    • 654
    • 655
    • 656
    • 657
    • 658
    • 659
    • 660
    • 661
    • 662
    • 663
    • 664
    • 665
    • 666
    • 667
    • 668
    • 669
    • 670
    • 671
    • 672
    • 673
    • 674
    • 675
    • 676
    • 677
    • 678
    • 679
    • 680
    • 681
    • 682
    • 683
    • 684
    • 685
    • 686
    • 687
    • 688
    • 689
    • 690
    • 691
    • 692
    • 693
    • 694
    • 695
    • 696
    • 697
    • 698
    • 699
    • 700
    • 701
    • 702
    • 703
    • 704
    • 705
    • 706
    • 707
    • 708
    • 709
    • 710
    • 711
    • 712
    • 713
    • 714
    • 715
    • 716
    • 717
    • 718
    • 719
    • 720
    • 721
    • 722
    • 723
    • 724
    • 725
    • 726
    • 727
    • 728
    • 729
    • 730
    • 731
    • 732
    • 733
    • 734
    • 735
    • 736
    • 737
    • 738
    • 739
    • 740
    • 741
    • 742
    • 743
    • 744
    • 745
    • 746
  • 相关阅读:
    第八章 操作位和位串(四)
    ArrayList集合源码分析
    Day29_8 Java学习之MySQL数据库
    【Spring从入门到实战】第1讲:为什么要学习Spring框架?
    LeetCode高频题36. 有效的数独
    【C语言基础】Chap. 2. 基本概念
    `Promise`全面解析
    ModifyAjaxResponse,修改ajax请求返回值,前后端调试之利器
    2023-09-02力扣每日一题
    浅析Linux进程间通信方式之磁盘映射(mmap)
  • 原文地址:https://blog.csdn.net/weixin_48052161/article/details/136650851