zoukankan      html  css  js  c++  java
  • es之java分页操作

    按照一般的查询流程来说,如果我想查询前10条数据:

    · 1 客户端请求发给某个节点

    · 2 节点转发给个个分片,查询每个分片上的前10条

    · 3 结果返回给节点,整合数据,提取前10条

    · 4 返回给请求客户端

    那么当我想要查询第10条到第20条的数据该怎么办呢?这个时候就用到分页查询了。

    浅分页可以理解为简单意义上的分页。它的原理很简单,就是查询前20条数据,然后截断前10条,只返回10-20的数据。这样其实白白浪费了前10条的查询。

    构造数据:

    /**插入一百条数据*/
    @Test
    // 批量查询100条记录
    public void createDocument100() throws Exception {
       for(int i=1;i<=100;i++){
           XContentBuilder builder = null;
           try {
               builder = jsonBuilder()
                      .startObject()
                      .field("title", "第"+i+"本书")
                      .field("author", "作者"+i)
                      .field("id" , i)
                      .field("message", i+"是英国物理学家斯蒂芬·霍金创作的科学著作,首次出版于1988年。全书共十二章,讲的全都是关于宇宙本性的最前沿知识,包括:我们的宇宙图像、空间和时间、膨胀的宇宙、不确定性原理、黑洞、宇宙的起源和命运等内容,深入浅出地介绍了遥远星系、黑洞、粒子、反物质等知识")
                      .endObject();
               String json = builder.string();
               IndexResponse response = this.client.prepareIndex("blog2", "article")
                      .setSource(json, XContentType.JSON)
                      .get();
               // 索引名称
               String _index = response.getIndex();
               // 类型
               String _type = response.getType();
               // 文档ID
               String _id = response.getId();
               // 版本
               long _version = response.getVersion();
               // 返回的操作状态
               RestStatus status = response.status();
               System.out.println("索引名称:"+_index+" "+"类型 :" +  _type + " 文档ID:"+_id+" 版本 :"+_version+" 返回的操作状态:"+status);

          } catch (IOException e) {
               e.printStackTrace();
          }
      }
    }

    1.9.1:浅分页

    /**
    * 查询所有的方法
    searchRequestBuilder 的 setFrom【从0开始】 和 setSize【查询多少条记录】方法实现
    * */
    @Test
    public void sortPages(){
       // 搜索数据
       // get() === execute().actionGet()
       SearchRequestBuilder searchRequestBuilder = transportClient.prepareSearch("blog2").setTypes("article")
              .setQuery(QueryBuilders.matchAllQuery());//默认每页10条记录
       final long totalHits = searchRequestBuilder.get().getHits().getTotalHits();//总条数
       final int pageDocument = 10 ;//每页显示多少条
       final long totalPage = totalHits / pageDocument;//总共分多少页
       for(int i=1;i<=totalPage;i++){
           System.out.println("=====================当前打印的是第 :"+i+" 页==============");
           //setFrom():从第几条开始检索,默认是0。
           //setSize():查询多少条文档。
           searchRequestBuilder.setFrom(i*pageDocument).setSize(pageDocument);

           SearchResponse searchResponse = searchRequestBuilder.get();
           SearchHits hits = searchResponse.getHits();
           Iterator<SearchHit> iterator = hits.iterator();
           while (iterator.hasNext()) {
               SearchHit searchHit = iterator.next(); // 每个查询对象
               System.out.println(searchHit.getSourceAsString()); // 获取字符串格式打印
          }
      }
    }

    1.9.2:分页优化-深分页(scroll)

    对于上面介绍的浅分页,当Elasticsearch响应请求时,它必须确定docs的顺序,排列响应结果。

    如果请求的页数较少(假设每页20个docs), Elasticsearch不会有什么问题,但是如果页数较大时,比如请求第20页,Elasticsearch不得不取出第1页到第20页的所有docs,再去除第1页到第19页的docs,得到第20页的docs。

     

    解决的方式就是使用scroll,scroll就是维护了当前索引段的一份快照信息--缓存(这个快照信息是你执行这个scroll查询时的快照)在这个查询后的任何新索引进来的数据,都不会在这个快照中查询到。但是它相对于from和size,不是查询所有数据然后剔除不要的部分,而是记录一个读取的位置,保证下一次快速继续读取。

     

    可以把 scroll 分为初始化和遍历两步: 1、初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照; 2、遍历时,从这个快照里取数据,也就是说,在初始化后对索引插入、删除、更新数据都不会影响遍历结果

    @Test
    public void scrollPages(){
       //获取Client对象,设置索引名称,搜索类型(SearchType.SCAN)[5.4移除,对于java代码,直接返回index顺序,不对结果排序],搜索数量,发送请求
       SearchResponse searchResponse = transportClient
          .prepareSearch("blog2")
              .setSearchType(SearchType.DEFAULT)//执行检索的类别
              .setSize(10).setScroll(new TimeValue(1000)).execute()
              .actionGet();//注意:首次搜索并不包含数据
       //获取总数量
       long totalCount = searchResponse.getHits().getTotalHits();

       int page=(int)totalCount/(10);//计算总页数
       System.out.println("总页数: ================="+page+"=============");
       for (int i = 1; i <= page; i++) {
           System.out.println("=========================页数:"+i+"====================");

           searchResponse = transportClient
                  .prepareSearchScroll(searchResponse.getScrollId())//再次发送请求,并使用上次搜索结果的ScrollId
                  .setScroll(new TimeValue(1000)).execute()
                  .actionGet();
           SearchHits hits = searchResponse.getHits();
           for (SearchHit searchHit : hits) {

               System.out.println(searchHit.getSourceAsString()); // 获取字符串格式打印
          }

      }
    }

     

  • 相关阅读:
    和远哥一起了解Hadoop的MapReduce是如何运行的
    远哥跟你说 Spring的 classpath 通配符加载配置文件
    远哥Amoeba源码分析之:核心类说明
    远哥推荐:面向网络的数据库 Neo4j
    Hadoop 1.0.3 在CentOS 6.2上安装过程 [个人安装通过的全程记录]
    OpenShift 添加 URL Rewrite 重写支持
    Access中空值处理
    解决EOS启动“不能连接到Server”的问题
    [原创]用递归写的一个object 转换成JSON的函数
    JSON反序列的问题原因查找
  • 原文地址:https://www.cnblogs.com/niutao/p/10909283.html
Copyright © 2011-2022 走看看