ES 深入浅出系列(三)常用的ES检索功能梳理

在ES当中其实有非常多的查询功能,本文就来通过代码案例带大家梳理下不同的查询类型的具体含义分别是什么?

本文所选用的依赖内容如下:

xml 复制代码
 <dependencies>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>6.5.4</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.5.4</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
</dependencies>

Index插入操作

在进行案例讲解之前,我们首先需要创建一颗索引树,这里我们可以利用es-rest-high-level-client工具包的index函数去进行操作。

java 复制代码
      public static RestHighLevelClient getClient() {
        HttpHost httpHost = new HttpHost("这里写自己es的地址",9200);
        RestClientBuilder clientBuilder = RestClient.builder(httpHost);
        RestHighLevelClient client = new RestHighLevelClient(clientBuilder);
        return client;
    }
java 复制代码
 private RestHighLevelClient client = EsClient.getClient();
    private String index = "sms";
    private String type = "yidong";
    private ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void createEsData() throws IOException {
        Settings.Builder setting = Settings.builder()
                .put("number_of_shards", 3)
                .put("number_of_replicas", 1);
        SmsPO smsPO = new SmsPO();
        XContentBuilder mappings = JsonXContent.contentBuilder()
                .startObject()
                .startObject("properties")
                .startObject("mobile")
                .field("type", "text")
                .endObject()
                .startObject("corpName")
                .field("type", "text")
                .endObject()
                .startObject("smsContent")
                .field("type", "text")
                .endObject()
                .startObject("state")
                .field("type", "integer")
                .endObject()
                .startObject("operatorId")
                .field("type", "integer")
                .endObject()
                .startObject("province")
                .field("type", "text")
                .endObject()
                .startObject("ip")
                .field("type", "text")
                .endObject()
                .startObject("replyTotal")
                .field("type", "integer")
                .endObject()
                .startObject("fee")
                .field("type", "integer")
                .endObject()
                .startObject("createTime")
                .field("type", "date")
                .field("format", "yyyy-mm-dd")
                .endObject()
                .startObject("updateTime")
                .field("type", "date")
                .field("format", "yyyy-mm-dd")
                .endObject()
                .endObject()
                .endObject();
        CreateIndexRequest request = new CreateIndexRequest(index)
                .settings(setting)
                .mapping(type, mappings);
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(response);
    }

    @Test
    public void testInsertData() throws IOException {
        for (int i = 0; i < 100; i++) {
            SmsPO smsPO = new SmsPO();
            smsPO.setId((long) i);
            smsPO.setMobile("15778293032");
            smsPO.setIp("127.0.0.1");
            smsPO.setFee(i + 500);
            smsPO.setProvince("BeiJin");
            smsPO.setOperatorId(i);
            smsPO.setCreateTime(new Date());
            smsPO.setUpdateTime(new Date());
            String json = objectMapper.writeValueAsString(smsPO);
            IndexRequest indexRequest = new IndexRequest(index, type, smsPO.getId().toString());
            indexRequest.source(json, XContentType.JSON);
            IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
            System.out.println(indexResponse.getResult().toString());
        }
    }

               

上述代码可以结合自己的实际环境去修改es的地址。当你执行完创建索引和插入数据两段函数之后,可以在kibana上看到对应的数据信息:

Term查询

下边是使用term查询的代码案例:

java 复制代码
  @Test
    public void testTermQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);

        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.from(0);
        builder.size(5);
        builder.query(QueryBuilders.termQuery("province", "BeiJin"));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println(response);
    }

所谓的term查询可以理解为是精确匹配查询的意思。

Match查询

来看代码案例:

java 复制代码
    @Test
    public void testMatchQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.matchQuery("province", "BeiJin"));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println(response.getHits().getHits().length);
    }
  

其底层其实就是将关键字进行分词处理,拆解为多个组成部分,然后分别调用多次term查询进行精确匹配。

MultiMatch查询

来看代码案例:

java 复制代码
    @Test
    public void testMultiMatchQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //相当于是province和smsContent字段都会进行match匹配
        builder.query(QueryBuilders.multiMatchQuery("BeiJin", "province", "smsContent"));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println(response.getHits().getHits().length);
    }

使用multiMatch其实底层就是多个关键字的match查询,很好理解。

MatchAll查询

该查询的目的就是将es中的所有数据都给检索出来的意思。相关代码如下:

java 复制代码
 @Test
    public void testMatchAllQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //这里指定数量,如果不指定,默认最多10条
        builder.size(15);
        builder.query(QueryBuilders.matchAllQuery());
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println(response.getHits().getHits().length);
    }
 

这里可以利用size参数去指定你所需要检索的数据量。

Id检索

来看代码案例:

java 复制代码
@Test
    public void testIdsQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.idsQuery().addIds("2", "3", "4"));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHit[] result = response.getHits().getHits();
        if (result.length > 0) {
            for (SearchHit documentFields : result) {
                System.out.println(documentFields.getSourceAsString());
            }
        }
    }

这个就非常容易理解了,和MySQL的in查询有点类似,只不过es规定的是对主键id进行in查询。

Prefix检索

java 复制代码
@Test
    public void testPrefixQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.prefixQuery("province","Bei"));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHit[] result = response.getHits().getHits();
        if (result.length > 0) {
            for (SearchHit documentFields : result) {
                System.out.println(documentFields.getSourceAsMap());
            }
        }
    }
 

前缀检索其实看名字就很好理解出来了,类似于mysql的 where key like 'test%' 这种含义。

Fuzzy查询

代码案例如下:

java 复制代码
 @Test
    public void testFuzzyQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //及时出现了部分错别字,也是可以模糊识别的
        builder.query(QueryBuilders.fuzzyQuery("province","Beijin"));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHit[] result = response.getHits().getHits();
        if (result.length > 0) {
            for (SearchHit documentFields : result) {
                System.out.println(documentFields.getSourceAsMap());
            }
        }
    }

Fuzzy可以说是一种更为智能的模糊查询,要比MySQL的like查询强。例如我们es中存储的数据,province均为BeiJin,但是如果你所传入的参数有一些误差,礼物Beijin,Fuzzy底层是可以自动帮你兼容的。

WildCard查询

先来看代码:

java 复制代码
      public void testWildCardQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.wildcardQuery("ip","127*"));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHit[] result = response.getHits().getHits();
        if (result.length > 0) {
            for (SearchHit documentFields : result) {
                System.out.println(documentFields.getSourceAsMap());
            }
        }

使用wildCard查询,是可以支持通配符功能的,也是一种比较灵活的查询方式。

Range查询

java 复制代码
 @Test
    public void testRangeQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //及时出现了部分错别字,也是可以模糊识别的
        builder.query(QueryBuilders.rangeQuery("id").gt("95"));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHit[] result = response.getHits().getHits();
        if (result.length > 0) {
            for (SearchHit documentFields : result) {
                System.out.println(documentFields.getSourceAsMap());
            }
        }
    }

range查询是一种范围查询的类型,假设我们的id是数字类型,使用range可以检索大于某个特定值的区间数据。

aggregation查询

使用aggregation是一种统计类的查询功能,来看下边这段求最大值和最小值的代码案例:

java 复制代码
  //获取最大值和最小值
    @Test
    public void testAggregationQuery() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.aggregation(AggregationBuilders.extendedStats("agg").field("id"));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        ExtendedStats agg = response.getAggregations().get("agg");
        System.out.println(agg.getMax());
        System.out.println(agg.getMin());
    }
   
相关推荐
V+zmm1013422 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
搬码后生仔1 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
凡人的AI工具箱1 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
喝醉酒的小白2 小时前
Elasticsearch(ES)监控、巡检及异常指标处理指南
大数据·elasticsearch·搜索引擎
J不A秃V头A2 小时前
IntelliJ IDEA中设置激活的profile
java·intellij-idea
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
Lx3522 小时前
Pandas数据重命名:列名与索引为标题
后端·python·pandas