2012-09-05 85 views
4

在MongoDB的新版本中,我們可以使用$ elemMatch投影算子來限制查詢對數組中單個匹配元素的響應。 http://docs.mongodb.org/manual/reference/projection/elemMatch/

但似乎並沒有在貓鼬3現在還沒有工作,是例如:

{ 
_id: ObjectId(5), 
items: [1,2,3,45,4,67,9,4] 
} 

Folder.findOne({_id: Object(5)}, {$elemMatch: {$in: [1,67,9]}}) 
    .exec(function (err, doc) { 

}); 

我期望能獲得如下文檔:

{ 
_id: ObjectId(5), 
items: [1,67,9] 
} 

但不幸的是我」 m到處是所有項目文件:

{ 
_id: ObjectId(5), 
items: [1,2,3,45,4,67,9,4] 
} 
+1

@esaelPsnoroMoN此功能已添加到2.2中,如問題中給出的鏈接所示。 OP還在標題中引用了2.2版本。 – Thomas

+0

也許在你的findOne()調用中你需要ObjectId(5)而不是Object(5)? – drevicko

+0

MongoDB Node.JS Native Driver中存在同樣的問題 - 您可以在選項$ elemMatch中設置,但驅動程序始終返回所有子文檔。 如果你在mongodb控制檯中測試你的查詢,它的效果很好。 – user1873840

回答

-1

無論$ elemMatch也不MongoDB的通用電氣neral會過濾數組中的數據。 $ elemMatch可用於匹配文檔,但不會影響要返回的數據。您只能使用filter參數(find()findOne()調用的第二個參數)包含/排除記錄中的字段,但不能根據某些查詢輸入過濾結果。

+0

在2.2 [$ elemMatch現在支持作爲投影](http://docs.mongodb.org/manual/reference/projection/elemMatch/)。在以前的版本中,只有[$ elemMatch運算符](http://docs.mongodb.org/manual/reference/operator/elemMatch/)。 – Stennie

+0

那麼爲什麼它不適用貓鼬? – Erik

2

首先,您在$ elemMatch運算符前缺少items字段名稱。您的查詢應該讀

Folder.findOne({_id: Object(5)}, {items: {$elemMatch: {$in: [1,67,9]}}}) 
    .exec(function (err, doc) { }); 

但是,這仍然不會返回期望的結果,因爲在文檔中的規定:

的$ elemMatch投影將只匹配每個源 文件一個數組元素。

所以,你只能拿回類似:

{ 
_id: ObjectId(5), 
items: [1] 
} 
+0

您忘記了'項目'的更多大括號,查詢應爲:Folder.findOne({_ id:Object(5)},{items:{$ elemMatch:{$ in:[1,67,9] }}}) .exec(function(err,doc){}); – Erik

+0

@Erik謝謝你是對的。我把它固定在上面的文章中。 – Thomas

1

我沒有貓鼬建立與節點要做到這一點,但你也可以得到你想要使用新的聚合框架的結果在2.2中 - 這是一個能夠讓你得到你想要的結果的例子。首先,我的示例文檔看起來是這樣的:

> db.foo.findOne() 
{ 
    "_id" : ObjectId("50472eb566caf6af6108de02"), 
    "items" : [ 
     1, 
     2, 
     3, 
     45, 
     4, 
     67, 
     9, 
     4 
    ] 
} 

要得到你想要我這樣做的:

> db.foo.aggregate( 
      {$match : {"_id": ObjectId("50472eb566caf6af6108de02")}}, 
      {$unwind : "$items"}, 
      {$match : {"items": {$in : [1, 67, 9]}}}, 
      {$group : {_id : "$_id", items : { $push : "$items"}}}, 
      {$project : {_id : 0, items : 1}} 
    ) 
{ 
    "result" : [ 
    { 
     "_id" : ObjectId("50472eb566caf6af6108de02"), 
     "items" : [ 
      1, 
      67, 
      9 
     ] 
    } 
], 
"ok" : 1 

} 

的講解,詳細我會把它逐行:

{$match : {"_id": ObjectId("50472eb566caf6af6108de02")}} 

這非常明顯 - 它基本上等同於普通查詢的查找條件,結果會傳遞到要處理的管道中的下一個步驟。這是一塊可以使用索引等

{$unwind : "$items"} 

這會爆炸的陣列,創建文檔的流,一個用於所述陣列中的每個元素。

{$match : {"items": {$in : [1, 67, 9]}}} 

這第二場比賽將只返回列表中的文檔,基本上將文檔流減少到三個結果集。

{$group : {_id : "$_id", items : { $push : "$items"}}} 

我們希望我們的輸出是一個數組,所以我們上面現在我們已經選擇了我們想要的物品,使用_id爲重點,以組撤消放鬆。注意:這將有重複的值,如果有一個以上的比賽,如果你想你會使用$addToSet代替$push

{$project : {_id : 1, items : 1}} 

於是最後,是不是真的需要這個投影獨特的名單,但我把它列入到說明功能 - 如果您願意,您可以選擇不返回_id。

+0

謝謝你的回覆,但我認爲這是一個貓鼬的錯誤。我認爲使用聚合框架解決我的任務並不是一個好主意。 – Erik

+0

這不是一個錯誤,而是一個mongodb文檔問題。看到我下面的評論。 – aaronheckmann

+0

@Erik - 明白了,我只是想給你一個替代方案,而不是解決貓鼬/文檔問題,我以同樣的方式解決了類似的問題。 –