標籤:mongodb spring data mongodb spring
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 設定返回需要的欄位
MongoDB伺服器返回的查詢結果,當調用cursor.hasNext()時,MongoDB批量的大小不會超過最大BSON文檔大小,然而對於大多數查詢,第一批返回101文檔或足夠的檔案超過1 MB,後續的批大小為4 MB。如果第一批是返回101個文檔時,遍曆完時,執行hasNext,會到資料庫查詢結果,直到所有結果都被返回,遊標才會結關閉。
四.其他的查詢方法
mongoTemplate .findAll 查詢集合所有的文檔 相當於MongoDB的db.collect.find()。
mongoTemplate .findById 根據文檔_ID查詢對應的文檔。
mongoTemplate .findAndRemove 根據查詢條件,查詢匹配的文檔返回,並從資料庫中刪除。
我們在查詢時,這邊預設是有使用到索引,對於資料量大的文檔,需要建立合適的索引,加快查詢效率。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Spring Data MongoDB 五:進階文檔查詢(分頁、Morphia)(二)