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());
    }
   
相关推荐
罗曼蒂克在消亡几秒前
2.3MyBatis——插件机制
java·mybatis·源码学习
_GR12 分钟前
每日OJ题_牛客_牛牛冲钻五_模拟_C++_Java
java·数据结构·c++·算法·动态规划
coderWangbuer21 分钟前
基于springboot的高校招生系统(含源码+sql+视频导入教程+文档+PPT)
spring boot·后端·sql
无限大.25 分钟前
c语言200例 067
java·c语言·开发语言
余炜yw26 分钟前
【Java序列化器】Java 中常用序列化器的探索与实践
java·开发语言
攸攸太上27 分钟前
JMeter学习
java·后端·学习·jmeter·微服务
Kenny.志30 分钟前
2、Spring Boot 3.x 集成 Feign
java·spring boot·后端
不修×蝙蝠32 分钟前
八大排序--01冒泡排序
java
sky丶Mamba1 小时前
Spring Boot中获取application.yml中属性的几种方式
java·spring boot·后端
数据龙傲天1 小时前
1688商品API接口:电商数据自动化的新引擎
java·大数据·sql·mysql