簡述
通俗的說,游標不是查詢結果,可以理解為數據在遍歷過程中的內部指針,其返回的是一個資源,或者說數據讀取接口.
客戶端通過對游標進行一些設置就能對查詢結果進行有效地控制,如可以限制查詢得到的結果數量、跳過部分結果、或對結果集按任意鍵進行排序等!
直接對一個集合調用find()方法時,我們會發現,如果查詢結果超過二十條,只會返回二十條的結果,這是因為Mongodb會自動遞歸find() 返回的游標。
基本操作
當我們使用一個變量來保存 find()的返回值時,其將不會自動進行遍歷顯示查詢結果的操作,並沒有真正的去查詢數據庫,只要當用到的時候(也就是遍歷游標的時候)才會到數據庫中將數據取出來,和PHP鏈接mysql資源一樣:
php代碼
$result = mysql_query('select * from message'); //返回的是一個資源
$row=mysql_fetch_assoc($result);//返回sql查詢的數組(僅為滿足條件的第一條),其內部就有一個指針游標,可以通過循環反復的取出數據
while($f=mysql_fetch_assoc($result)){//每循環一次游標就前進一次,游標走到尾的時候,就不返回值了
$row[]=$f;
}
var_dump($row);
mongoDB代碼(js)
// while循環
var cursor = db.goods.find({goods_id:{$lte:20}},{_id:0,goods_id:1}); //使用變量來保存游標
while(cursor.hasNext()){ //cursor.hasNext()判斷游標是否取到盡頭
printjson(cursor.next()); //cursor.next()取出游標的下1個單元(從0開始游),注意print打印的是二進制對象,printjson打印出來的才是可閱讀的json格式數據
}
// for循環
var cursor = db.goods.find({goods_id:{$lte:100}},{_id:0,goods_id:1}); //使用變量來保存游標
for (;cursor.hasNext();) { //由於cursor.hasNext()自動判斷的特性這里的for循環可以很簡單
printjson(cursor.next());
}
//forEach循環
var cursor = db.goods.find({goods_id:{$lte:100}},{_id:0,goods_id:1,goods_name:1});
var callback = function(obj){ //obj就是查出的文檔對象
printjson(obj.goods_id) //直接取出goods_id的值;
}
cursor.forEach(callback);
游標在分頁中的應用 limit,skip,sort
比如查到10000行,跳過100頁,取10行.一般地,我們假設每頁N行, 當前是page頁,就需要跳過前 (page-1)*N 行, 再取N行, 在mysql中, limit offset,N來實現
在mongo中,用skip(), limit()函數來實現的,當獲得游標后,我們可以先對游標進行處理后,再讓訪問數據庫的動作按照我們的意願發生。在這里我們就可以使用limit,skip,sort三個函數來處理游標。同時這三個函數可以組成方法鏈式調用的形式。
limit:限制游標返回的數量,指定了上限
skip:忽略前面的部分文檔,如果文檔總數量小於忽略的數量,則返回空集合
sort:得到的子集合進行排序,可以按照多個鍵進行正反排序!
# 查詢5條
> var cursor = db.goods.find({},{_id:0,goods_id:1}).limit(5); //注意,再次使用游標的時候,游標得重置,因為使用過一次就游到最后了;
> cursor.forEach(function(obj){print(obj.goods_id);})
# 查詢5條,並按照shop_price的降序排列
> var cursor = db.goods.find({},{_id:0,goods_id:1,shop_price:1}).limit(5).sort({shop_price:-1})
> cursor.forEach(function(obj){
print(obj.goods_id+' '+obj.shop_price)
})
22 5999
23 3700
32 3010
18 2878
14 2625
# 每頁10條取第二頁,並且升序排列
var cursor = db.goods.find({},{_id:0,goods_id:1,shop_price:1}).limit(10).sort({goods_id:1}).skip(10)
cursor.forEach(function(obj){
print(obj.goods_id+' '+obj.shop_price)
})
# 一次性打印所有的行,以易讀的模式
var cursor = db.goods.find({},{_id:0,goods_id:1,shop_price:1});
printjson(cursor.toArray());
/*
注意: 不要隨意使用toArray()
原因: 會把所有的行立即以對象形式組織在內存里.可以在取出少數幾行時,用此功能.
*/