一.简介

 

     SpringData  MongoDB提供了org.springframework.data.mongodb.core.MongoTemplate对MongoDB的find的操作,我们上一篇介绍了基本文档的查询,我们今天介绍分页查询,分页查询是返回到匹配文档的游标,可以随意修改查询限制、跳跃、和排序顺序的功能。

     我们在查询时find()方法接受Query类型有org.springframework.data.mongodb.core.query和org.springframework.data.mongodb.core.query.BasicQuery

     Query类提供方法有limit、skip、sort查询限制、跳跃、和排序顺序的功能,BasicQuery继承了Query类。

 

Query

Mongodb

说明

Query limit (int limit)

limit

方法是限制游标返回结果的数量

Query skip (int skip)

skip

方法可以跳过指定值的条数,返回剩下的条数的结果,可以跟limit()方法进行组合可以实现分页的效果

Sort sort () 已过时

现在是用query.with(sort)

sort

方法来对数据进行排序,根据指定的字段,并使用1或-1来指定排序方式是升序或降序,类似于SQL的order by。

 

二.基本分页

 

    Query类提供方法有limit、skip、sort查询限制、跳跃、和排序顺序的功能,我们实现Query查询分页

 

     第一步:实现分页工具类

1. /**
2.  * 分页
3.  * @author zhengcy
4.  *
5.  * @param<T>
6.  */  
7. public classPageModel<T>{  
8. //结果集   
9.    privateList<T> datas;   
10. //查询记录数   
11.    privateintrowCount;   
12. //每页多少条数据   
13. 20;  
14. //第几页   
15. 1;  
16. //跳过几条数  
17. 0;   
18. /**
19.      * 总页数
20.      * @return
21.      */   
22.    publicintgetTotalPages(){   
23. return(rowCount+pageSize-1)/pageSize;   
24.    }  
25.      
26. public List<T>getDatas() {  
27. return datas;  
28.    }  
29. public void setDatas(List<T>datas) {  
30. this.datas = datas;  
31.    }  
32. public int getRowCount() {  
33. return rowCount;  
34.    }  
35. public void setRowCount(int rowCount) {  
36. this.rowCount = rowCount;  
37.    }  
38. public int getPageSize() {  
39. return pageSize;  
40.    }  
41. public void setPageSize(int pageSize) {  
42. this.pageSize = pageSize;  
43.    }  
44. public int getSkip() {  
45. 1)*pageSize;  
46. return skip;  
47.    }  
48. public void setSkip(int skip) {  
49. this.skip = skip;  
50.    }  
51.    
52. public int getPageNo() {  
53. return pageNo;  
54.    }  
55.    
56. public void setPageNo(int pageNo) {  
57. this.pageNo = pageNo;  
58.    }   
59.     
60.      
61.      
62. }

   第二步:实现分页

     

1. @Override  
2. public PageModel<Orders>getOrders(PageModel<Orders> page, DBObject queryObject,StringcollectionName) {  
3.    Queryquery=newBasicQuery(queryObject);  
4. //查询总数  
5. int count=(int) mongoTemplate.count(query,Orders.class);  
6.    page.setRowCount(count);  
7.     
8. //排序  
9. new Sort(Direction.ASC, "onumber"));  
10.      query.skip(page.getSkip()).limit(page.getPageSize());  
11. class);  
12.    page.setDatas(datas);  
13. return page;  
14. }


说明:

   Sort :sort () 已过时,现在是用query.with(sort),with参数是sort类

   Sort提供了几种构造函数

      

MongoDB 分页 工具类 spring data mongodb 分页_字段

   方法的描述

      (1)一个字段的排序

          例如onumber字段升序

        query.with(new Sort(Direction.ASC,"onumber"));

     (2)如果是多个字段时同时升序或者降序时

       //排序

        query.with(new Sort(Direction.ASC,"a","b","c"));

 

   (3)不同的字段按照不同的排序

1. List<Sort.Order>orders=new ArrayList<Sort.Order>();  
2. orders.add(newSort.Order(Direction.ASC, "a"));  
3. orders.add(newSort.Order(Direction.DESC, "b"));  
4. query.with(newSort(orders ));

        

   第三步:测试类

        

1.  @Test  
2. public void testList() throws ParseException  
3. {  
4.   PageModel<Orders>page=newPageModel<Orders>();  
5. 1);  
6. new BasicDBObject("cname","zcy"),collectionName);  
7. "总数:"+page.getRowCount());  
8. "返回条数:"+page.getDatas().size());  
9.   System.out.println(JSONArray.fromObject(page.getDatas()));  
10. }

 

cname=zcy

            

MongoDB 分页 工具类 spring data mongodb 分页_分页_02

        

      skip方法是跳过条数,而且是一条一条的跳过,如果集合比较大时(如书页数很多)skip会越来越慢, 需要更多的处理器(CPU),这会影响性能。

三、进阶的查询分页

 

      返回到匹配文档的游标,可以随意修改查询限制、跳跃、和排序顺序的功能,我们这边对指针返回的结果,我用到Morphia框架。

Morphia是一个开放源代码的对象关系映射框架,它对MongoDB数据库 Java版驱动进行了非常轻量级的对象封装。我们需要通过DBCurosr获取的DBObject转换成我们对应的实体对象,方便我们操作实体。

     DBCurosr 是 DBCollection 的 find 方法返回的对象,可以设置 skip、limit 、sot等属性执行分页查询

 

   第一步:在实体id要注解@id

     

importcom.google.code.morphia.annotations.Id;
           @Id
         privateString id;

 

     @Id 注释指示Morphia哪个字段用作文档 ID

 

     如果没加的话,会出现这样的错误

 

...27 more
Caused by: com.google.code.morphia.mapping.validation.ConstraintViolationException: Number of violations: 1
NoId complained aboutcom.mongo.model.Orders. : No field is annotated with @Id; but it is required
    atcom.google.code.morphia.mapping.validation.MappingValidator.validate(MappingValidator.java:66)
    atcom.google.code.morphia.mapping.validation.MappingValidator.validate(MappingValidator.java:155)
    atcom.google.code.morphia.mapping.MappedClass.validate(MappedClass.java:259)
    atcom.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:154)
    atcom.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:142)
    atcom.google.code.morphia.Morphia.map(Morphia.java:55)
    atcom.mongo.dao.impl.OrdersDaoImpl.<init>(OrdersDaoImpl.java:37)
    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    atsun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    atsun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    atjava.lang.reflect.Constructor.newInstance(Unknown Source)
    atorg.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
    ... 29more

 

 

  第二步:实现:


1.    privateMorphia  morphia;  
2.     
3. public OrdersDaoImpl(){  
4. new Morphia();  
5. class);  
6.    }  
7. @Override  
8. public PageModel<Orders>getOrders(PageModel<Orders> page, DBObject queryObject,StringcollectionName) {  
9.    
10.       DBObjectfilterDBObject=newBasicDBObject();  
11. "_id", 0);  
12. "cname",1);  
13. "onumber",1);  
14.          
15.       DBCursordbCursor=mongoTemplate.getCollection(collectionName).find(queryObject,filterDBObject);  
16.        
17. //排序  
18.       DBObjectsortDBObject=newBasicDBObject();  
19. "onumber",1);  
20.       dbCursor.sort(sortDBObject);  
21. //分页查询  
22.       dbCursor.skip(page.getSkip()).limit(page.getPageSize());  
23.        
24. //总数  
25. int count=dbCursor.count();  
26. //循环指针  
27.       List<Orders>datas=newArrayList<Orders>();  
28. while (dbCursor.hasNext()) {  
29. class, dbCursor.next()));  
30.       }  
31.        
32.       page.setRowCount(count);  
33.       page.setDatas(datas);  
34. return page;  
35. }


 我们开始执行DAO时,先初始化Morphia,并往里面添加我们需要转换的实体类CLASS

morphia=new Morphia();
morphia.map(Orders.class);

DBObject),  dbCursor.Next()获取DBObject时,我们通过Morphia把DBObject对应的实体类。

  查询时通过filterDBObject 设置返回需要的字段

     

MongoDB 分页 工具类 spring data mongodb 分页_分页_03

 

      MongoDB服务器返回的查询结果, 当调用cursor.hasNext()时,MongoDB批量的大小不会超过最大BSON文档大小,然而对于大多数查询,第一批返回101文档或足够的文件超过1 MB,后续的批大小为4 MB。如果第一批是返回101个文档时,遍历完时,执行hasNext,会到数据库查询结果,直到所有结果都被返回,游标才会结关闭。

 


 

四.其他的查询方法

     mongoTemplate .findAll   查询集合所有的文档 相当于MongoDB的db.collect.find()。

     mongoTemplate .findById  根据文档_ID查询对应的文档。

     mongoTemplate .findAndRemove  根据查询条件,查询匹配的文档返回,并从数据库中删除。


     我们在查询时,这边默认是有使用到索引,对于数据量大的文档,需要建立合适的索引,加快查询效率。