2012-08-27 141 views
1

美好的一天每個人。 假設我們有一個集合,它看起來是這樣的文件:從文檔中檢索單個屬性

test_doc = { 
    "ID" : "123", 
    "a" : [ 
        { 
         'x' : "/", 
         'y' : "2000", 
         'z' : "1000" 
        }, 
        { 
         'x' : "/var", 
         'y' : "3500", 
         'z' : "3000" 
        } 
      ] 

     } 

我需要的是檢索單個屬性a.z。 在MongoDB中我使用下面的查詢:

db.testcol.find({"ID":"123","a.x":"/"},{'a.z':1}) 

返回此:

{ "_id" : ObjectId("skipped"), "a" : [ { "z" : "1000" }, { "z" : "3000" } ] } 

正如你可以看到它返回所有z屬性,但我只需要第一個或第二當條件是{"ID":"123","a.x":"/var"} 所以,問題是:如何在這種情況下獲得單一財產?這只是一個糟糕的設計問題,或者我應該以某種方式處理代碼(python)中返回的文檔?任何建議將不勝感激。

回答

1

在MongoDB 2.0及更高版本中,這是不可能的。你想要做的是返回數組的一個特定元素 - 但這不是你的投影實際做的,它只會返回整個數組,然後返回每個元素的z元素。

然而,2.2(寫這個答案時的rc2),事情變得更好了。您現在可以使用$elemMatch作爲投影的一部分(有關詳細信息,請參閱SERVER-2238),以便您只需拉回所需的數組元素。因此,嘗試這樣的事情:

db.foo.find({"ID":"123",'a':{$elemMatch:{'x':"/"}}},{_id : 0, 'a.$': 1}) 
//returns 
{ "a" : [ { "x" : "/", "y" : "2000", "z" : "1000" } ] } 

或者,只是在投影本身,你可能會認爲使用$ elemMatch是清潔:

db.foo.find({"ID":"123"},{_id : 0, 'a':{$elemMatch:{'x':"/"}}}) 
//returns 
{ "a" : [ { "x" : "/", "y" : "2000", "z" : "1000" } ] } 

所以,現在,至少返回的數組是唯一隻包含你想要的條目,並且你可以簡單地引用相關的z元素(對子文檔中的elemMatch投影還不被支持)。

最後但並非最不重要的一點,在2.2中我們有聚合框架,它可以做的其中一件事(使用$project運算符,是重塑你的文檔並將子文檔和數組元素轉換爲頂層數組。你期望的結果,你會做這樣的事情:

db.foo.aggregate( 
     {$match : {"ID":"123"}}, 
     {$unwind : "$a"}, 
     {$match : {"a.x":"/"}}, 
     {$project : {_id : 0, z : "$a.z"}} 
) 

結果看起來是這樣的:

{ "result" : [ { "z" : "1000" } ], "ok" : 1 } 
+1

感謝您的快速答覆,亞當其實我想對$ elemMatch過,但我有點困惑它如何工作。你的答案現在事情很明確。 – user91730

+0

我還添加了一個如何使用聚合框架來做到這一點的例子 - 我需要先測試它,然後才能包含它:) –

+1

Wow聚合似乎是一個非常整潔的功能。例如Thx,有用的:) – user91730