1.准备环境

  1.1 mongodb下载

  1.2 mongodb启动

    C:\mongodb\bin\mongod --dbpath D:\mongodb\data

  1.3 可视化mongo工具Robo 3T下载

2.准备数据

  

  1. <dependency>
  2. <groupId>org.mongodb</groupId>
  3. <artifactId>mongo-java-driver</artifactId>
  4. <version>3.6.1</version>
  5. </dependency>

java代码执行

  1. public static void main(String[] args) {
  2.  
  3. try {
  4.  
  5. /**** Connect to MongoDB ****/
  6. // Since 2.10.0, uses MongoClient
  7. MongoClient mongo = new MongoClient("localhost", 27017);
  8.  
  9. /**** Get database ****/
  10. // if database doesn't exists, MongoDB will create it for you
  11. DB db = mongo.getDB("www");
  12.  
  13. /**** Get collection / table from 'testdb' ****/
  14. // if collection doesn't exists, MongoDB will create it for you
  15. DBCollection table = db.getCollection("person");
  16.  
  17. /**** Insert ****/
  18. // create a document to store key and value
  19. BasicDBObject document=null;
  20.  
  21. for(int i=0;i<100000000;i++) {
  22. document = new BasicDBObject();
  23. document.put("name", "mkyong"+i);
  24. document.put("age", 30);
  25. document.put("sex", "f");
  26. table.insert(document);
  27. }
  28.  
  29. /**** Done ****/
  30. System.out.println("Done");
  31.  
  32. } catch (UnknownHostException e) {
  33. e.printStackTrace();
  34. } catch (MongoException e) {
  35. e.printStackTrace();
  36. }
  37.  
  38. }

3.分页查询

 传统的limit方式当数据量较大时查询缓慢,不太适用。考虑别的方式,参考了logstash-input-mongodb的思路:

  1. public
  2. def get_cursor_for_collection(mongodb, mongo_collection_name, last_id_object, batch_size)
  3. collection = mongodb.collection(mongo_collection_name)
  4. # Need to make this sort by date in object id then get the first of the series
  5. # db.events_20150320.find().limit(1).sort({ts:1})
  6. return collection.find({:_id => {:$gt => last_id_object}}).limit(batch_size)
  7. end
  8.  
  9. collection_name = collection[:name]
  10. @logger.debug("collection_data is: #{@collection_data}")
  11. last_id = @collection_data[index][:last_id]
  12. #@logger.debug("last_id is #{last_id}", :index => index, :collection => collection_name)
  13. # get batch of events starting at the last_place if it is set
  14.  
  15. last_id_object = last_id
  16. if since_type == 'id'
  17. last_id_object = BSON::ObjectId(last_id)
  18. elsif since_type == 'time'
  19. if last_id != ''
  20. last_id_object = Time.at(last_id)
  21. end
  22. end
  23. cursor = get_cursor_for_collection(@mongodb, collection_name, last_id_object, batch_size)

使用java实现

  1. import java.net.UnknownHostException;
  2. import java.util.List;
  3.  
  4. import org.bson.types.ObjectId;
  5.  
  6. import com.mongodb.BasicDBObject;
  7. import com.mongodb.DB;
  8. import com.mongodb.DBCollection;
  9. import com.mongodb.DBCursor;
  10. import com.mongodb.DBObject;
  11. import com.mongodb.MongoClient;
  12. import com.mongodb.MongoException;
  13.  
  14. public class Test {
  15.  
  16. public static void main(String[] args) {
  17. int pageSize=50000;
  18.  
  19. try {
  20.  
  21. /**** Connect to MongoDB ****/
  22. // Since 2.10.0, uses MongoClient
  23. MongoClient mongo = new MongoClient("localhost", 27017);
  24.  
  25. /**** Get database ****/
  26. // if database doesn't exists, MongoDB will create it for you
  27. DB db = mongo.getDB("www");
  28.  
  29. /**** Get collection / table from 'testdb' ****/
  30. // if collection doesn't exists, MongoDB will create it for you
  31. DBCollection table = db.getCollection("person");
  32. DBCursor dbObjects;
  33. Long cnt=table.count();
  34. //System.out.println(table.getStats());
  35. Long page=getPageSize(cnt,pageSize);
  36. ObjectId lastIdObject=new ObjectId("5bda8f66ef2ed979bab041aa");
  37.  
  38. for(Long i=0L;i<page;i++) {
  39. Long start=System.currentTimeMillis();
  40. dbObjects=getCursorForCollection(table, lastIdObject, pageSize);
  41. System.out.println("第"+(i+1)+"次查询,耗时:"+(System.currentTimeMillis()-start)/1000+"秒");
  42. List<DBObject> objs=dbObjects.toArray();
  43. lastIdObject=(ObjectId) objs.get(objs.size()-1).get("_id");
  44.  
  45. }
  46.  
  47. } catch (UnknownHostException e) {
  48. e.printStackTrace();
  49. } catch (MongoException e) {
  50. e.printStackTrace();
  51. }
  52.  
  53. }
  54.  
  55. public static DBCursor getCursorForCollection(DBCollection collection,ObjectId lastIdObject,int pageSize) {
  56. DBCursor dbObjects=null;
  57. if(lastIdObject==null) {
  58. lastIdObject=(ObjectId) collection.findOne().get("_id"); //TODO 排序sort取第一个,否则可能丢失数据
  59. }
  60. BasicDBObject query=new BasicDBObject();
  61. query.append("_id",new BasicDBObject("$gt",lastIdObject));
  62. BasicDBObject sort=new BasicDBObject();
  63. sort.append("_id",1);
  64. dbObjects=collection.find(query).limit(pageSize).sort(sort);
  65. return dbObjects;
  66. }
  67.  
  68. public static Long getPageSize(Long cnt,int pageSize) {
  69. return cnt%pageSize==0?cnt/pageSize:cnt/pageSize+1;
  70. }
  71.  
  72. }

4.一些经验教训

  1. 不小心漏打了一个$符号,导致查询不到数据,浪费了一些时间去查找原因

  1. query.append("_id",new BasicDBObject("$gt",lastIdObject));
    2.创建索引
      创建普通的单列索引:db.collection.ensureIndex({field:1/-1});  1是升续 -1是降续
    实例:db.articles.ensureIndex({title:1}) //注意 field 不要加""双引号,否则创建不成功
      查看当前索引状态: db.collection.getIndexes();
      实例:
      db.articles.getIndexes();
      删除单个索引db.collection.dropIndex({filed:1/-1});

3.执行计划

  db.student.find({"name":"dd1"}).explain()

参考文献:

【1】https://github.com/phutchins/logstash-input-mongodb/blob/master/lib/logstash/inputs/mongodb.rb

【2】https://www.cnblogs.com/yxlblogs/p/4930308.html

【3】https://docs.mongodb.com/manual/reference/method/db.collection.ensureIndex/

亿级别记录的mongodb分页查询java代码实现的更多相关文章

  1. 亿级别记录的mongodb批量导入Es的java代码完整实现

    针对mongodb亿级别或者十亿级别的模糊查询,效率不高,解决方式是使用Es查询,这样就需要把数据导入的ES中 完整的代码实现如下所示:(仅供参考) import java.io.IOExceptio ...

  2. MongoDB分页的Java实现和分页需求的思考

    前言 传统关系数据库中都提供了基于row number的分页功能,切换MongoDB后,想要实现分页,则需要修改一下思路. 传统分页思路 假设一页大小为10条.则 //page 1 1-10 //pa ...

  3. Mybatis包分页查询java公共类

    Mybatis包分页查询java公共类   分页----对于数据量非常大的查询中.是不可缺少的. mybatis底层的分页sql语句因为须要我们自己去手动写.而实现分页显示的时候我们须要依据分页查询条 ...

  4. 分页查询关键代码 多条件查询关键代码 删除选中商品关键代码 修改要先回显再修改 修改要先回显再修改 同一业务集中使用同一servlet的方法

    分页查询关键代码: 通过servlet转发回来的各种信息进行分页的设计(转发回的信息有 分页查询的List集合 查询的页码 查询的条数 查询的数据库总条数 查询的总页码) 从开始时循环10次出现十个数 ...

  5. MongoDB 分页查询的方法及性能

    最近有点忙,本来有好多东西可以总结,Redis系列其实还应该有四.五.六...不过<Redis in Action>还没读完,等读完再来总结,不然太水,对不起读者. 自从上次Redis之后 ...

  6. C#MongoDB 分页查询的方法及性能

    传统的SQL分页 传统的sql分页,所有的方案几乎是绕不开row_number的,对于需要各种排序,复杂查询的场景,row_number就是杀手锏.另外,针对现在的web很流行的poll/push加载 ...

  7. Spring Data MongoDB 分页查询

    在上篇文章 Spring Data MongoDB 环境搭建 基础上进行分页查询 定义公用分页参数类,实现 Pageable 接口 import java.io.Serializable; impor ...

  8. (记录)mysql分页查询,参数化过程的坑

    在最近的工作中,由于历史遗留,一个分页查询没有参数化,被查出来有sql注入危险,所以对这个查询进行了参数化修改. 一看不知道,看了吓一跳,可能由于种种原因,分页查询sql是在存储过程中拼接出来的,wh ...

  9. 使用mybatis实现分页查询示例代码分析

    *******************************************分页查询开始*************************************************** ...

随机推荐

  1. 关于如何参与到开源项目中《How To Succeed In Open Source ( In Ways You Haven't Considered Yet )》

    转自:http://gaslight.co/blog/how-to-succeed-in-open-source-in-ways-you-havent-considered-yet It’s Easy ...

  2. 使用像素单位设置 EXCEL 列宽或行高

    在导出 Excel 的时候, 经常要需要给列设置宽度或给行设置高度, 在使用 NPOI 或 EppPlus 等组件进行操作的时候, 列宽和行高的单位都不是像素, 好像是英寸,具体是啥也说不清. 平常在 ...

  3. ActiveX 控件重绘无效问题,用CClientDC 而不是CPaintDC

    ActiveX 控件重绘子控件时,用Invalid()会出现无效的情况即不会更新界面. OnPaint 方法里,是用的 CPaintDC,经测试无效,后换CClientDC,发现可以,百度查他们的区别 ...

  4. WPF 降低.net framework到4.0

    1. 问题背景 由于xp系统上面最高只能安装.net framework 4.0,所以公司项目需要将原来项目的.net framework版本降低到4.0,具体的降版本很简单,只要把项目属性中的目标框 ...

  5. 【OCP|052】OCP最新题库解析系列-3

    3.Which structure can span multiple data files?❑ A) a permanent tablespace❑ B) a bigfile tablespace❑ ...

  6. Java 设计模式——单例模式

    Java有很多的设计模式,但是让我们一个个分析出来,可能就一脸蒙逼了,今天就和大家一块来分析一下Java中的一些常用的设计模式.今天先分析单例模式 单例模式的好处 举个例子:有一个类,里面有若干个公共 ...

  7. css 实现关闭按钮 X

    .close::before { content: "\2716";} 然后就显示出来了 这里有个更直接的例子 <!DOCTYPE html> <html lan ...

  8. php脚本cli 模式运行

    参考文章 http://rapheal.sinaapp.com/2013/11/20/php_zend_hello_world/ http://www.douban.com/note/33788568 ...

  9. 题目1001:A+B for Matrices(简单循环)

    问题来源 http://ac.jobdu.com/problem.php?pid=1001 问题描述 给你两个形式相同的矩阵,对应位置相加得到新矩阵,计算里面全为0的行数和列数. 问题分析 这里其实只 ...

  10. canvas+js绘制序列帧动画+面向对象

    效果: 素材: 源码:(一般的绘制方式) <!DOCTYPE html> <html lang="en"> <head> <meta ch ...