2017-10-17 103 views
0

我想創建一個查詢或聚合,其中返回的文檔不包含子文檔。我不知道給定的字段會提前作爲子文檔(或者我只是使用投影來跳過它們)。因此,舉例來說,如果我有一個這樣的文件:MongoDB查詢或聚合以跳過子文檔

{ 
    _id: 1, 
    field1: "a", 
    field2: "b", 
    field3: { 
    subfield1: "c", 
    subfield2: "d" 
    } 
} 

當我查詢返回這個文件,它要麼跳過場3,或者用別的東西(例如一個字符串=「field_is_an_object」)取代場3的值。

正如我所說,我不知道哪些字段將是子文檔(或「對象」類型)。 $ redact操作符是我能找到的最接近的,但我無法弄清楚它的工作原理。

回答

0

有,你可以達到你想要的東西至少有兩種方式:

第一個是非常簡潔,只需要一個聚合階段,然而,有一點更復雜,更難理解:

db.collection.aggregate({ 
    $replaceRoot: { // create a new top level document 
     "newRoot": { // ...which shall be 
      $arrayToObject: { // ...created from an array 
       $filter: { // ...that again should contain only those elements 
        input: { // ...from our input array 
         $objectToArray: "$$ROOT" // ...which is our respective top level document transformed into an array of key-value pairs 
        }, 
        cond: { // ...where 
         $ne: [ { $type: "$$this.v" }, "object" ] // ...the "v" (as in "value" field is not an object) 
        } 
       } 
      } 
     } 
    } 
}) 

我能想到的第二個方法比較冗長,但通過逐步添加階段(像聚合框架一樣)非常容易理解。

db.collection.aggregate({ 
    $project: { 
     "tmp": { // we create a temporary field 
      $objectToArray: "$$ROOT" // that contains our respective root document represented as an array of key-value pairs 
     } 
    } 
}, { 
    $unwind: "$tmp" // flatten the temporary array into multiple documents 
}, { 
    $match: { 
     "tmp.v": { $not: { $type: "object" } } // filter all documents out that we do not want in our result 
    } 
}, { 
    $group: { // group all documents together again 
     "_id": "$_id", // into one bucket per original document ("_id") 
     "tmp": { 
      $push: "$tmp" // and create an array with all the key-value pairs that have survived our $match stage 
     } 
    } 
}, { 
    $replaceRoot: { // create a new top level document... 
     "newRoot": { 
      $arrayToObject: "$tmp" // ...out of the data we have left in our array 
     } 
    } 
}) 
+0

這工作......謝謝。詳細的解釋也很有幫助。我唯一的意見是,$ objectToArray操作在3.6中是新的,並且3.6還沒有正式發佈。我安裝了最新的3.6版RC,它確實有效。 –

+0

它在3.4中可用:https://docs.mongodb.com/manual/reference/operator/aggregation/objectToArray/ – dnickless

+0

那真是令人尷尬。我在3.4.0,所以它不適合我;我可以發誓我看到了一些說「添加到3.6」的東西,所以這就是我安裝的東西。雖然文檔清楚地表明它是在3.4.4中添加的。再次感謝。 –