2014-09-06 41 views
2

這裏是我的示例文件:通過投影從嵌套的文件全部刪除,但一個領域

{ 
    a: 42, 
    map: { 
    x: { ... }, 
    y: { ... }, 
    z: { ... } 
    } 
} 

我正在尋找一種方法來僅返回:

{ 
    a: 42, 
    map: { 
    y: { ... } 
    } 
} 

我只想說明地圖內的字段保持爲。類似的東西...

db.myCollection.find({}, 
    { 
    "map.y":1 
    } 
) 

... 也應該返回現場a沒有明確指定它。

我知道我也可以刪除不需要的映射條目:

db.myCollection.find({}, 
    { 
    "map.x":0, 
    "map.z":0 
    } 
) 

可是這樣一來,我需要知道在我運行查詢該地圖鍵可用。

有沒有一種很好的方法來處理這個問題?也許使用聚合框架?

謝謝:)

回答

2

這基本上是如何投影或字段選擇MongoDB中以及許多其它數據庫系統的工作原理。這裏的概念基本上是「全部或全部」,因爲如果你沒有指定你想返回的所有字段,它們不會被返回,當然默認是返回你沒有具體說明你想要的東西。

因此,對當前數據的正確形式只返回amap.y是:

db.myCollection.find({}, { "a": 1, "map.y": 1 }) 

或者當然你告訴它你不想要的東西:

db.myCollection.find({}, { "map.x": 0, "map.z": 0 }) 

但你不能「混合」包含和排除,唯一的例外是_id字段,您不希望在結果中使用該字段,可能會想到「覆蓋索引」查詢,但通常需要主鍵:

db.myCollection.find({}, { "_id": 0, "a": 1, "map.y": 1 }) 

至於聚合框架,它是相同的,特別和同樣殘酷的運營商,如$project$group。在這兩種情況下,您都需要明確指定要返回的內容($ project也遵循通用投影規則),或者這些字段不在結果中。

事實上,一個常見的錯誤使我的人們與這些階段中的一個「清除」字段,然後試圖指的是後來被移除的字段。這是一個「管道」,就像Unix管道|一樣,流向下一個階段的唯一內容是你指定的內容:

唯一的「真實」情況,你可以排除除匹配字段外的所有內容而不指定其他字段是通過改變你的結構來實現「map」作爲一個數組,然後使用從MongoDB 2.6及更高版本可用的流水線階段。雖然有點做作:

db.test.insert({ 
    "a": 42, 
    "map": [ 
     { "type": "x", "content": {} }, 
     { "type": "y", "content": {} }, 
     { "type": "z", "content": {} } 
    ] 
}) 

而且在結構類似於該數據的聚合操作:

db.test.aggregate([ 
    { "$redact": { 
     "$cond": [ 
      { "$eq": [ 
       { "$ifNull": [ "$type", "y" ] }, 
       "y" 
      ]}, 
      "$$DESCEND", 
      "$$PRUNE" 
     ] 
    }} 
]) 

就這樣,我們只要求元素與「型」匹配等於「Y」,但你由於$ redact正在遞歸處理,因此一般需要小心,這就是爲什麼$ifNull運算符人爲地在測試字段不存在的級別創建匹配。

但通常情況下,投影是全部或沒有。指定您想要返回的字段或者他們不會在那裏。

+0

太糟糕了,因爲數組不會映射到我的Java類。但我當然可以解決這個問題。 '...'現在我有第二個小問題了:當使用'type'和'content'的數組方法時,是否可以使用'elemMatch'運算符與投影相反?即(僞代碼)'map:{$ elemMatch:{type:NOT「y」}}:0',所以它會從數組中刪除所有內容,其中'type!=「y」'。 – 2014-09-06 05:02:29

+0

@BenjaminM正如我所解釋的,沒有其他方式可以讓另一個領域(如「a」)出現,而沒有特別說明你想要返回。 $ redact是從文檔中「刪除」元素的特殊情況,在這種情況下,「類型」字段不匹配。所以沒有其他方式意味着沒有其他辦法。 – 2014-09-06 05:10:55

+0

謝謝,對於'!!!'這個偉大的解釋,我將不得不考慮一下。我可以使用第二個集合作爲'map',然後我可以很容易地使用標準投影。 – 2014-09-06 05:12:37