ES中的三种查询

这篇具有很好参考价值的文章主要介绍了ES中的三种查询。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Es有三种查询方式,不知道你平时工作中用到的是哪种呢?
一、from+Size
1、深度分页或者size特别大的时候,会出现deep pagination问题.并且因为Es自身的保护机制(max_result_window是10000),如果查出来的数据量大于10000的就会报错.
2、该查询的实际原理类似于mysql中的limit,比如查询第10001条数据,那么需要将前面的10000条都拿出来,进行过滤,最终才得到数据(性能比较差,实现简单,适用于少量数据).

二、scroll
1、高效进行滚动查询,首次查询会在内存中保存一个历史快照以及游标(scroll_id),记录当前消息查询的终止位置,下次查询的时候将基于游标进行消费(性能良好,不具备实施性,一般是用于大量数据导出或索引重建)
2、可以查询10000条以上数据.
3、当使用完查询的数据之后,记得要手动清理,因为scroll查询会生成快照,虽然会有过期时间,但是如果并发访问量激增的时候,都没达到过期时间,就会导致内存溢出.

三、search after
1、缺点是不能够随机跳转分页,只能是一页一页的向后翻(当有新数据进来,也能实时查询到),并且需要至少指定一个唯一不重复字段来排序(一般是_id)
2、当使用search_after时,from值必须设置为0或者-1
3、可以查询10000条以上数据.

from+size demo

		QueryBuilder query = new QueryBuilder();
		SearchRequest searchRequest = new SearchRequest(index);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
        	// 分页参数
            .from(page.getPage())
            .size(page.getSize())
            .trackTotalHits(true)
            // 过滤条件
            .query(query);
        if (sort != null) {
        	// 排序
            searchSourceBuilder.sort(sort.getSortFiled(), sort.getSortOrder());
            searchSourceBuilder.sort("_id", SortOrder.DESC);
        }
        if (fields != null) {
        	// 查询的结果字段
            searchSourceBuilder.fetchSource(fields, null);
        }
        searchRequest.source(searchSourceBuilder);
        try {
        	// 进行查询
            SearchResponse searchResponse = restClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null) {
                return EsResult.EMPTY;
            }
            // 结果转换,clazz是对应的DTO
            List<T> data = covert2JavaBeanList(searchHits.getHits(), clazz);
            return new EsResult<>(NumberUtils.toInt(String.valueOf(searchHits.getTotalHits().value)), data);
        } catch (IOException e) {
            EsExceptionUtil.dealIOException(e);
        } catch (ElasticsearchException e1) {
            EsExceptionUtil.dealElasticsearchException(e1);
        }
        return EsResult.EMPTY;

scroll demo

		// 设置过期时间
		Scroll scroll = new Scroll(TimeValue.timeValueMinutes(30));
		SearchResponse searchResponse = null;
        if (StringUtils.isEmpty(scrollId)) {
            // 1.构建SearchRequest检索请求
            // 专门用来进行全文检索、关键字检索的API
            SearchRequest searchRequest = new SearchRequest(index);

            // 2.创建一个SearchSourceBuilder专门用于构建查询条件
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .trackTotalHits(true)
                .query(query);

            if (CollectionUtils.isNotEmpty(sorts)) {
                for (EsSort sort : sorts) {
					// 排序字段                    
                    searchSourceBuilder.sort(sort.getSortFiled(), sort.getSortOrder());
                }
            }
            if (fields != null) {
                searchSourceBuilder.fetchSource(fields, null);
            }
            // 每页显示多少条
            searchSourceBuilder.size(pageSize);
            // 4.调用SearchRequest.source将查询条件设置到检索请求
            searchRequest.source(searchSourceBuilder);
            //--------------------------
            // 设置scroll查询
            //--------------------------
            searchRequest.scroll(scroll);

            try {
                searchResponse = restClient.search(searchRequest, RequestOptions.DEFAULT);
                return gettEsScrollResult(clazz, searchResponse);
            } catch (IOException e) {
                EsExceptionUtil.dealIOException(e);
            } catch (ElasticsearchException e1) {
                EsExceptionUtil.dealElasticsearchException(e1);
            }

        }
        // 第二次查询的时候,直接通过scroll id查询数据
        else {
            SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
            searchScrollRequest.scroll(scroll);

            // 使用RestHighLevelClient发送scroll请求
            try {
                searchResponse = restClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);
                return gettEsScrollResult(clazz, searchResponse);
            } catch (IOException e) {
                EsExceptionUtil.dealIOException(e);
            } catch (ElasticsearchException e1) {
                EsExceptionUtil.dealElasticsearchException(e1);
            }
        }

        SearchHits searchHits;
        List<T> data = Lists.newArrayList();
        if (searchResponse != null) {
            searchHits = searchResponse.getHits();
            data = covert2JavaBeanList(searchHits.getHits(), clazz);
        } else {
            searchHits = SearchHits.empty();
        }

        return new EsScrollResult<>(NumberUtils.toInt(String.valueOf(searchHits.getTotalHits().value)), searchResponse != null ? searchResponse.getScrollId() : "", data);

手动清理scroll demo

	public void clearScroll(List<String> scrollIds) {
        if (CollectionUtils.isEmpty(scrollIds)) {
            return;
        }
        List<String> notEmptyIds = scrollIds.stream().filter(o -> !StringUtils.EMPTY.equals(o)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(notEmptyIds)) {
            return;
        }
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
        notEmptyIds.forEach(clearScrollRequest::addScrollId);
        try {
            ClearScrollResponse clearScrollResponse = restClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
            log.info("清理scrollId:{},状态:{},释放空间:{}", notEmptyIds, clearScrollResponse.isSucceeded(), clearScrollResponse.getNumFreed());
        } catch (IOException e) {
            log.warn("清理scroll失败", e);
        }

    }

search after demo

		SearchRequest searchRequest = new SearchRequest(index);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
            .query(query)
            .fetchSource(fields, null)
            .trackTotalHits(true)
            .size(pageSize);
            // 判断是否是第一次查询
        if (sortValues != null && sortValues.length != 0) {
            searchSourceBuilder.searchAfter(sortValues);
        }
        boolean idSort = false;
        if (CollectionUtils.isNotEmpty(sorts)) {
            for (EsSort sort : sorts) {
                searchSourceBuilder.sort(sort.getSortFiled(), sort.getSortOrder());
        		// 保证有唯一的排序字段
                if ("_id".equals(sort.getSortFiled())) {
                    idSort = true;
                }
            }
        }
        if (!idSort) {
            throw new EsDataException("排序参数必须包含_id");
        }
        searchRequest.source(searchSourceBuilder);
        try {
            SearchResponse searchResponse = restClient.search(searchRequest, RequestOptions.DEFAULT);
            if (searchResponse.getHits() == null || searchResponse.getHits().getHits().length == 0) {
                return EsSearchAfterResult.EMPTY;
            }
            SearchHit[] searchHits = searchResponse.getHits().getHits();
            List<T> data = covert2JavaBeanList(searchHits, clazz);
            // 取出最后一条记录的位置
            SearchHit lastHit = searchHits[searchHits.length - 1];
      		// 得到最后一条记录的sortValue值,返回给调用方,让调用方作为下一页查询的条件
            Object[] lastSortValues = lastHit.getSortValues();
            return new EsSearchAfterResult<>(NumberUtils.toInt(String.valueOf(searchResponse.getHits().getTotalHits().value)), data, lastSortValues);
        } catch (IOException e) {
            EsExceptionUtil.dealIOException(e);
        } catch (ElasticsearchException e1) {
            EsExceptionUtil.dealElasticsearchException(e1);
        }
        return EsSearchAfterResult.EMPTY;

总结:
1、from + size的大小和es的保护机制的大小要一致,否则会报错
2、使用scroll的时候一定要记得要记得手动清理掉缓存
3、searchAfter 一定要设置唯一的排序字段,否则可能导致数据查询的少.文章来源地址https://www.toymoban.com/news/detail-409017.html

到了这里,关于ES中的三种查询的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据表的清空有三种方式:

    1.delete------ 是逐行删除速度极慢,不适合大量数据删除。 Delete from tablename where 1=1 2.truncate---- 删除所有数据,保留表结构,不能撤消还原。 TRUNCATE TABLE tablename 3.drop-------- 删除表,数据和表结构一起删除,快速。 SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for

    2023年04月10日
    浏览(50)
  • PHP的curl有三种Post请求数据的方式

    今天要讲的HTTP请求头的Content-Type字段,就是在curl发送post请求的时候需要指定以何种方式来请求数据,常用的有3类: 1、form-data 。就是 multipart/form-data 使用表单的方式来发送数据 是curl采用的默认发送方式。请求数组类型的格式。 Content-Type: multipart/form-data 2、x-www-form-urlenco

    2024年02月11日
    浏览(76)
  • 修改Docker容器中的mysql时区的三种方式

    一、临时修改时区 // 查看linux时区 date -R // 查看mysql的时区 show variables like ‘%time_zone%’ // 查看当前时间 select now() // 设置全局 set global time_zone = ‘+8:00’ // 设置当前会话 set global time_zone = ‘+8:00’ // 立即生效 flush privileges 二.、 永久修改Docker容器中mysql的时区 我们通常在创建

    2024年02月03日
    浏览(41)
  • 【SpringBoot】读取application.yml配置中的三种方式

    applicaiton.yml BootValueApplicationTests.java 打印如下所示 注意的地方 当对应的值不存在时,系统会报错。我们可以给定一个默认值即可。 如下所示: 在这里,sys.noValue这个值是不存在的,我们可以给定一个默认值为123,当然,我们如果不指定默认值的,它的默认值为空字符串。 优

    2024年02月13日
    浏览(53)
  • 使用maven打包时如何跳过test,有三种方式

    方式一 针对spring项目: 针对springboot:  方式二(通用 ): 方式三(通用): mvn package -DskipTests=true -DskipTests=true,不执行测试用例,但编译测试用例类生成相应的class文件至 target/test-classes 下。   mvn package -Dmaven.test.skip=true -Dmaven.test.skip=true,不执行测试用例,也不编译测试

    2024年02月13日
    浏览(41)
  • mysql中的实现字段或字符串拼接的三种方式

    concat函数是将多个字段或字符串拼接为一个字符串;但是字符串之间没有任何分隔。 concat函数官方介绍 执行结果如下: 执行结果如下: 如果拼接的字段中有一个为null,则结果为null。 执行结果如下: concat_ws函数将多个字段或字符串拼接为一个字符串,且字符串直接可以指定

    2024年02月22日
    浏览(98)
  • selenium中的三种等待方式以及显示等待和隐式等待区别

    selenium中一般分为三种等待方式:显示等待、隐式等待、sleep强制等待 1、显示等待(有条件) 程序提前指定等待条件和等待时间,在查找元素时,判断规定时间内是否满足条件,满足则继续执行,不满足或超出时间则抛出异常 2、隐式等待(无条件) 程序提前指定等待时间,在查

    2024年02月12日
    浏览(40)
  • 数据库中的字段名与实体类中的属性名不能一一对应时的三种处理方式

    当查询结果的列名和java对象的属性名对应不上时需要采用下列方式进行处理:         第一种方式:在查询语句中使用\\\"as\\\" 给列起别名         第二种方式:使用resultMap结果映射         第三种方式:开启驼峰命名自动映射(配置settings) 实体类Car: packa

    2024年02月09日
    浏览(42)
  • JavaScript 中问号的三种用法 ??和?.以及?: 您知道吗?

     最近看了一些关于JavaScript的测试脚本,觉得JS 中问号的用法还是蛮有意思的,于是做了一下总结,在这里分享给大家!JS中的问号大概有三种用法,分别是:空值合并操作符、可选链操作符和三目运算。 空值合并操作符??是一个逻辑操作符,当左侧的操作数为 null 或者 und

    2024年02月11日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包