2017-10-17 70 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中添加的。再次感谢。 –