MongoDB 學習四 : 查詢(續)

來源:互聯網
上載者:User

標籤:

接著上章,繼續介紹MongoDB的查詢。

 

Querying on Embedded Documents

有兩種方式查詢嵌入式的子Documents:查詢整個Document或者查詢個別的索引值對。

查詢整個子Document和正常的查詢是一樣的。

我們有一個document:

{     "name":{           "first":"Joe",           "last":"Schmoe"           },      "age":45}

我們可以尋找名為Joe Schmoe的人:

db.people.find({"name":{"first":"Joe","last":"Schmoe"}})

然而,查詢一個子Document必須精確匹配。假如Joe決定添加一個中間名欄位,那麼上面這個查詢就不成立了。

並且,這種查詢類型同樣是順序敏感,{"last":"Schmoe","first":"Joe"},這樣查詢也是不匹配的。

通常針對子文檔的key進行尋找就不會出現上述的情況了:

db.people.find({"name.last":"Schmoe","name.first":"Joe"})

 

下來我們來看這條資料:

{   "content":"...",   "comments":[         {             "author":"joe",             "score":3,             "comment":"nice post"          },         {             "author":"mary",             "score":6,             "comment":"terrible post"          }    ]}

現在我們想要尋找comments為joe並且得分大於5.

首先,我們不能這樣查詢

db.blog.find({"comments":{"author":"joe","score":{"$gte":5}}})

內嵌文檔匹配要求整個文檔完全符合,而不是匹配comments這個key。

同樣我們不能用

db.blog.find({"comments.author":"joe","comments.score":{"$gte":5}})

因為符合author條件的評論和符合score的評論可能不是同一條。也就是說會返回剛才顯示的那個document。因為"author"在第一條評論中實現,"score"在第二條評論中實現。

正確的該如何呢?

db.blog.find({"comments":{"$elemMatch":{"author":"joe","score":{"$gte":5}}}})

 "$elemMatch"將限定條件進行分組,僅當需要一個內嵌文檔的多個鍵操作時才會用到。

$where Queries

索引值對是極富表現力的查詢方式,但是有些查詢他們也不能表達。

這時候,"$where"子句查詢就出場了,它允許你在你的查詢中執行任意的Javascript

最典型的應用就是比較文檔中的兩個鍵的值是否相等,例如有個條目列表,如果其中的兩個值相等則返迴文檔。例:

db.foo.insert({"apple":1,"banana":6,"peach":3})db.foo.insert({"apple":8,"spinach":4,"watermelon":4})

第二個文檔中,"spinach"和"watermelon"的值相同,所以需要返回該文檔。

db.foo.find({"$where":function(){         for(var current in this){              for(var other in this){                    if(current !=other && this[current]==this[other]){                               return ture;                     }              }          }          return false;}})

如果函數返回為true,文檔就作為結果的一部分被返回。

在非必要時,不要用"$where":它的查詢速度比一般查詢要慢很多。

 

Cursors

資料庫使用遊標來返回find的執行結果。用戶端對遊標的實現通常能夠對最終結果進行有效控制。

你可以限制結果的數量,略過部分結果,根據任意方向任意鍵的組合對結果進行各種排序,或者執行其他的一些功能強大的操作。

想從Shell中建立一個遊標,首先要對集合填充一些文檔,然後對其進行查詢,並將結果分配給一個局部變數。這裡,建立一個簡單集合,而後做查詢,並用cursor儲存結果:

for(i=0;i<100;i++){      db.collection.insert({x:i});}
var cursor = db.collection.find()

這麼做的好處是一次可以查看一條結果。如果將結果放在全域變數或者沒有放在變數中,MongoDB Shell會自動迭代,自動顯示最開始的若干文檔。

也就是在這之前我們看到的種種例子,一般大家只想通過Shell看看集合裡面有什麼,而不是想在其中運行程式,這樣的設計就很合適。

要迭代結果,可以使用遊標的next方法。也可以使用hasNext來查看有沒有其他的結果。典型的遍曆如下:

while(cursor.hasNext()){     obj = cursor.next();     //do stuff}

遊標類還實現了迭代介面,所以可以在forEach迴圈中使用。

var cursor = db.people.find();cursor.forEach(function(x){      print(x.name)})

當使用find的時候,shell並不立即查詢資料庫,而是等待真正開始要求獲得結果的時候才發送查詢,這樣在執行之前可以給查詢附加額外的選項。

幾乎所有遊標對象的方法都返回遊標本身,這樣就可以按任意順序組成方法鏈。如下面幾種是等價的:

var cursor = db.foo.find().sort({"x":1}).limit(1).skip(10);var cursor = db.foo.find().limit(1).sort({"x":1}).skip(10);var cursor = db.foo.find().skip(10).limit(1).sort({"x":1});

此時,查詢還沒有執行,所有這些函數都只是構造查詢。假設我們執行

cursor.hasNext();

這時,查詢發往伺服器。shell立即擷取錢100個結果或者前4M資料(兩者之間較小者),這樣下次調用next或者hasNext時就不必興師動眾跑到伺服器上去了。

用戶端用光了第一組結果,shell會再次串連資料庫,並要求更多的結果。這個過程一直會持續到遊標耗盡或者結果全部返回。

MongoDB 學習四 : 查詢(續)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.