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

一、簡介

    db.collection.find()可以實現根據條件查詢和指定使用投影運算符返回的字段省略此參數返回匹配文檔中的所有字段。並返回到匹配文檔的遊標,可以隨意修改查詢限制、跳躍、和排序順序的功能。

 

二、db.collection.findOne ()

     db.collection. findOne ()返回滿足指定查詢條件的文檔。如果多個文檔滿足查詢,該方法返回第一個文檔,根據自然順序返回文件在磁盤上的順序,在覆蓋的集合中,自然順序與插入順序相同。

  

   語法:

   db.collection.findOne(query, projection)


參數

類型

描述

query

document

可選. 使用查詢操作符指定查詢條件

projection

document

指定使用投影運算符返回的字段省略此參數返回匹配文檔中的所有字段

 

Projection語法:

 

 { field1: <boolean>, field2: <boolean> ... }


說明:

   1或者true表示返回字段

   0或者false表示不返回該字段


    先插入數據

    

>db. orders.insert([
{
        "onumber" : "001", 
        "date" : "2015-07-02", 
        "cname" : "zcy1", 
        "items" :[ {
        "ino" : "001",
                  "quantity" :2, 
                  "price" : 4.0
         },{
                 "ino" : "002",
                  "quantity" : 4, 
                  "price" : 6.0
           }
         ]
},{
        "onumber" : "002", 
        "date" : "2015-07-02", 
        "cname" : "zcy2", 
        "items" :[ {
                  "ino" : "001",
                  "quantity" :2, 
                  "price" : 4.0
                 },{
                  "ino" : "002",
                  "quantity" :6, 
                  "price" : 6.0
                  }
               ]
}
])
  

  我們用db.orders.find()查詢時返回多條記錄

   >db.orders.find({"date":"2015-07-02"})

     

 

   我們執行db.orders.findOne()時,只返回第一條記錄

 

 例子:

<span style="font-size:18px;">  >db.orders.findOne({"date":"2015-07-02"})</span>

       

 

二、遊標的遍歷

     db.collection.find()可以實現根據條件查詢和指定使用投影運算符返回的字段省略此參數返回匹配文檔中的所有字段。並返回到匹配文檔的遊標,可以隨意修改查詢限制、跳躍、和排序順序的功能。

  

   1、我們先通過javascript腳本向集合中填充10000條文檔,然後執行db.collection.find()執行查詢文檔

     

> for(var i=0;i<10000;i++){
...db.items.insert({"ino":i,"quantity":i});
... }
WriteResult({ "nInserted" : 1 })
> db.items.find()
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681076"), "ino" : 0,"quantity" : 0 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681077"), "ino" : 1,"quantity" : 1 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681078"), "ino" : 2,"quantity" : 2 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681079"), "ino" : 3,"quantity" : 3 }
{ "_id" : ObjectId("55a66f3c7db4e9f2ef68107a"),"ino" : 4, "quantity" : 4 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107b"), "ino" : 5,"quantity" : 5 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107c"), "ino" : 6,"quantity" : 6 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107d"), "ino" : 7, "quantity": 7 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107e"), "ino" : 8,"quantity" : 8 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107f"), "ino" : 9,"quantity" : 9 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681080"), "ino" : 10,"quantity" : 10 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681081"), "ino" : 11,"quantity" : 11 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681082"), "ino" : 12,"quantity" : 12 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681083"), "ino" : 13,"quantity" : 13 }
{ "_id" : ObjectId("55a66f3c7db4e9f2ef681084"),"ino" : 14, "quantity" : 14 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681085"), "ino" : 15,"quantity" : 15 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681086"), "ino" : 16,"quantity" : 16 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681087"), "ino" : 17,"quantity" : 17 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681088"), "ino" : 18,"quantity" : 18 }
{ "_id" :ObjectId("55a66f3c7db4e9f2ef681089"), "ino" : 19,"quantity" : 19 }
Type "it" for more
> 

       我們db.collection.find()執行查詢文檔時,發現Mongo shell如果沒有分配給一個使用var關鍵字的變量迭代數據時,光標自動迭代前20個文檔的結果返回。

       輸入“it”後會顯示後二十條的數據。

 

   2、你可以使用DBQuery.shellbatchsize改變迭代次數(每頁就顯示10條記錄)

 

      例子:

      

     >DBQuery.shellBatchSize = 10
       

         

 

         現在光標自動迭代前10個文檔的結果返回

 

   3、我們定義一個變量來保存這個遊標

 

        例子:

      > var cursor=db.items.find()
     

        

   

      用一個變量來保存遊標,不會自動輸出數據的,需要我們自己實現這個查詢結果的遊標進行遍歷。

 

   4、對遊標進行遍歷


    >var cursor=db.items.find()
    >while(cursor.hasNext()){ 
      var doc = cursor.next();
      printjson(doc);
    };

    或者

     forEach()循環遍歷:

   

   >cursor.forEach( function(doc) { printjson(doc);});


       當你遍歷遊標到返回的批處理結束,如果有更多的結果,cursor.next()將執行更多的操作來獲取下一批。

      MongoDB服務器返回的查詢結果, 當調用cursor.hasNext()時,MongoDB批量的大小不會超過最大BSON文檔大小,然而對於大多數查詢,第一批返回101文檔或足夠的文件超過1 MB,後續的批大小爲4 MB。如果第一批是返回101個文檔時,遍歷完時,執行hasNext,會到數據庫查詢結果,直到所有結果都被返回,遊標纔會結關閉。

 

     我們可以通過可以使用objsleftinbatch()方法來查看,每次返回文檔數量或者大小,如下面的例子:

   >var cursor=db.items.find()
   >cursor .objsLeftInBatch();

     


      當我們剛執行查詢時,執行cursor .objsLeftInBatch();方法會顯示101 ,這說明第一批返回101文檔(101文檔沒超過1MB)

 

      我們遍歷完101個文檔時,當我們執行cursor.hasNext()時,第二批會在返回101文檔嗎?

     我們先遍歷完101個文檔,如下面的例子:

   >for(vari=0;i<101;i++){
      var doc = cursor.next();
      printjson(doc);
    }


     這時我們迭代完第一批返回的結果,我們在執行cursor.hasNext();時,會到數據庫查詢下一批結果,我們objsLeftInBatch方法查看返回文檔大小,如下面的例子:

   

   >cursor.hasNext();
   >cursor .objsLeftInBatch();

    

   

      這時返回的結果是 9899, 不在是101個文檔,而是4 MB,我們9899個文檔沒達到4MB,所有全部返回。

 

  說明:

      MongoDB使用的是內存映射存儲引擎,它會把磁盤IO操作轉換成內存操作,如果是讀操作,內存中的數據起到緩存的作用。查詢時,實現分批次返回結果,這是一個懶加載的過程,需要時纔到數據庫查詢下一批結果,這會節省資源,不會浪費資源。

 

三、遊標的操作

     我們還可以對文檔的遊標,可以隨意修改返回結果的限制、跳躍、和排序順序的功能。

 

       1. limit

         

           limit方法是限制遊標返回結果的數量,如下面例子:

       >db.items.find().limit(5)

           

          只返回結果5條文檔

 

       2.sort

              sort()方法來對數據進行排序,根據指定的字段,並使用1或-1來指定排序方式是升序或降序,類似於SQL的order by。

                

               例子:

          >db.items.find({"ino":{$lt:5}}).sort({"quantity":-1})
 

                 

  

              我們查詢ino小於5,並對這結果進行排序,按quantity字段降序。


              我們可以指定多個字段排序,例如我們先按quantity字段降序,然後在按info升序,如下面的例子:

               

         >db.items.find({"ino":{$lt:5}}).sort({"quantity":-1,"info":1})
            

            


              我們查詢ino小於5,並對這結果進行排序,按quantity字段降序

 

              我們還可以跟limit()方法進行組合查詢並對結果進行排序

              例子:

              

        >db.items.find().limit(3).sort({"quantity":1})
               

 

             我們先根據quantity字段升序並返回前3條記錄,發現沒有鍵quantity(即鍵quantity值爲null)的文檔排在了前面,這是在MongoDB中,當比較不同類型值BSON,MongoDB使用以下比較順序,從最低到最高:

  1. MinKey (internal type)
  2. Null
  3. Numbers (ints, longs, doubles)
  4. Symbol, String
  5. Object
  6. Array
  7. BinData
  8. ObjectId
  9. Boolean
  10. Date
  11. Timestamp
  12. Regular Expression
  13. MaxKey (internal type)


      對於包括一個沒有索引的排序操作的查詢,服務器必須在返回任何結果之前將所有的文檔加載到內存中來進行排序。

     3、skip


       skip方法可以跳過指定值的條數,返回剩下的條數的結果,可以跟limit()方法進行組合可以實現分頁的效果。

       

         例子:

      >db.items.find().skip(10).limit(10)

               

           跳過第10條,從第11條開始返回,只返回10條文檔.

           skip方法是跳過條數,而且是一條一條的跳過,如果集合比較大時(如書頁數很多)skip會越來越慢, 需要更多的處理器(CPU),這會影響性能。

我們可以通過一個鍵值比較有順序的來進行分頁,這樣就避免使用skip方法。

           

             例子:

                

          >db.items.find({"ino":{$lt:20,$gt:9}}).sort({"info":1})
                

                 

 

四、遊標的說明

        默認情況下,服務器將自動關閉該遊標10分鐘後閒置或客戶端遍歷完結果的遊標。需要手動關閉遊標或清除遊標是,可以在查詢中使用光標指定noTimeout標記。通過  cursor.addOption(),通過這個方法,如下面的例子:

        

     >var cursor = db.items.find().addOption(DBQuery.Option.noTimeout);


    可以查看遊標信息:

      (1) 打開的遊標的總數

      (2)當前客戶端使用的遊標大小

      (3)自上次重新啓動服務器的超時遊標數量


      我們可以查看,瞭解遊標使用情況


      如下面的例子:

        

     >db.serverStatus().metrics.cursor

       

    

      





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章