Spring Data MongoDB 五:進階文檔查詢(分頁、Morphia)(二)


    Spring Data MongoDB 三:基本文檔查詢(Query、BasicQuery)(一)

    學習MongoDB 六: MongoDB查詢(游標操作、游標信息)(三)

     

一.簡單介紹

 

     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查詢分頁

 

     第一步:實現分頁工具類

/**
 * 分頁
 * @author zhengcy
 *
 * @param<T>
 */
public classPageModel<T>{
    //結果集 
   privateList<T> datas; 
   //查詢記錄數 
   privateintrowCount; 
   //每頁多少條數據 
   privateintpageSize=20;
   //第幾頁 
   privateintpageNo=1;
   //跳過幾條數
   privateintskip=0; 
   /**
     * 總頁數
     * @return
     */ 
   publicintgetTotalPages(){ 
        return(rowCount+pageSize-1)/pageSize; 
   }
   
   public List<T>getDatas() {
      return datas;
   }
   public void setDatas(List<T>datas) {
      this.datas = datas;
   }
   public int getRowCount() {
      return rowCount;
   }
   public void setRowCount(int rowCount) {
      this.rowCount = rowCount;
   }
   public int getPageSize() {
      return pageSize;
   }
   public void setPageSize(int pageSize) {
      this.pageSize = pageSize;
   }
   public int getSkip() {
      skip=(pageNo-1)*pageSize;
      return skip;
   }
   public void setSkip(int skip) {
      this.skip = skip;
   }
 
   public int getPageNo() {
      return pageNo;
   }
 
   public void setPageNo(int pageNo) {
      this.pageNo = pageNo;
   } 
  
   
   
}


   第二步:實現分頁

       

   @Override
   public PageModel<Orders>getOrders(PageModel<Orders> page, DBObject queryObject,StringcollectionName) {
      Queryquery=newBasicQuery(queryObject);
      //查詢總數
      int count=(int) mongoTemplate.count(query,Orders.class);
      page.setRowCount(count);
     
      //排序
         query.with(new Sort(Direction.ASC, "onumber"));
        query.skip(page.getSkip()).limit(page.getPageSize());
      List<Orders>datas=mongoTemplate.find(query,Orders.class);
      page.setDatas(datas);
      return page;
   }


說明:

   Sort :sort () 已過時。如今是用query.with(sort)。with參數是sort類

   Sort提供了幾種構造函數

      

   方法的描寫敘述

      (1)一個字段的排序

          比如onumber字段升序

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


     (2)假設是多個字段時同一時候升序或者降序時

       //排序

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

 

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

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

          a升序在按b降序


   第三步:測試類

        

       @Test
      public void testList() throws ParseException
      {
        PageModel<Orders>page=newPageModel<Orders>();
        page.setPageNo(1);
        page=ordersDao.getOrders(page, new BasicDBObject("cname","zcy"),collectionName);
        System.out.println("總數:"+page.getRowCount());
        System.out.println("返回條數:"+page.getDatas().size());
        System.out.println(JSONArray.fromObject(page.getDatas()));
      }

 

   查詢條件是cname=zcy

            

        

      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

 

 

  第二步:實現:

   privateMorphia  morphia;
  
   public OrdersDaoImpl(){
      morphia= new Morphia();
      morphia.map(Orders.class);
   }
   @Override
   public PageModel<Orders>getOrders(PageModel<Orders> page, DBObject queryObject,StringcollectionName) {
 
      DBObjectfilterDBObject=newBasicDBObject();
      filterDBObject.put("_id", 0);
      filterDBObject.put("cname",1);
      filterDBObject.put("onumber",1);
       
      DBCursordbCursor=mongoTemplate.getCollection(collectionName).find(queryObject,filterDBObject);
     
      //排序
      DBObjectsortDBObject=newBasicDBObject();
      sortDBObject.put("onumber",1);
      dbCursor.sort(sortDBObject);
      //分頁查詢
      dbCursor.skip(page.getSkip()).limit(page.getPageSize());
     
      //總數
      int count=dbCursor.count();
      //循環指針
      List<Orders>datas=newArrayList<Orders>();
      while (dbCursor.hasNext()) {
        datas.add(morphia.fromDBObject(Orders.class, dbCursor.next()));
      }
     
      page.setRowCount(count);
      page.setDatas(datas);
      return page;
}

   我們開始運行DAO時,先初始化Morphia,並往里面加入我們須要轉換的實體類CLASS

      morphia=new Morphia();

      morphia.map(Orders.class);

      

   dbCursor.hasNext()推斷是否還有下一個文檔(DBObject),  dbCursor.Next()獲取DBObject時。我們通過Morphia把DBObject相應的實體類。

  查詢時通過filterDBObject 設置返回須要的字段

     

 

      MongoDBserver返回的查詢結果, 當調用cursor.hasNext()時。MongoDB批量的大小不會超過最大BSON文檔大小,然而對於大多數查詢,第一批返回101文檔或足夠的文件超過1 MB,興許的批大小為4 MB。假設第一批是返回101個文檔時,遍歷完時,運行hasNext,會到數據庫查詢結果。直到全部結果都被返回,游標才會結關閉。

 


 

四.其它的查詢方法

     mongoTemplate .findAll   查詢集合全部的文檔 相當於MongoDB的db.collect.find()。

     mongoTemplate .findById  依據文檔_ID查詢相應的文檔。

     mongoTemplate .findAndRemove  依據查詢條件。查詢匹配的文檔返回。並從數據庫中刪除。


     我們在查詢時,這邊默認是有使用到索引,對於數據量大的文檔,須要建立合適的索引。加快查詢效率。






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM