2017-10-17 12 views
0

返された文書にサブ文書が含まれていないクエリまたは集計を作成したいとします。私は与えられたフィールドが事前にサブドキュメントになることを知らない(または私はちょうどそれらをスキップするために投影を使用する)。だから私はこのような文書があれば、たとえば、:サブ文書をスキップするMongoDBクエリまたは集計

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

を私のクエリはこの文書を返すとき、それはFIELD3をスキップのいずれか、または何か他のもの(例えば、文字列=「field_is_an_object」)とフィールド3の値を置き換えます。

私が言ったように、どのフィールドがサブドキュメント(または「オブジェクト」タイプ)になるかは事前に分かりません。 $ redact演算子は私が見つけることができる最も近いものでしたが、動作させるための構文を理解できませんでした。

答えて

0

あなたが欲しいものを達成することができる少なくとも2つの方法があります。

は最初のものはかなり簡潔で、しかし、もう少し複雑で理解しにくい、ただ一つの集約の段階が必要です。

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) 
        } 
       } 
      } 
     } 
    } 
}) 

私が考えることができる2つ目は、ステージを段階的に追加することで、より冗長ではありますが、わかりやすい方法です(いつものように集約フレームワークで)。

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はまだ公式にリリースされていないということです。私は最新のRC 3.6をインストールしました。 –

+0

3.4から入手できます:https://docs.mongodb.com/manual/reference/operator/aggregation/objectToArray/ – dnickless

+0

これは恥ずかしいことです。私は3.4.0だったので、私にとってはうまくいかなかった。私は「3.6で追加されました」と言ったことを誓ったことがあるので、それは私がインストールしたものです。ドキュメントには、3.4.4で追加されたことが明確に書かれていますが。再度、感謝します。 –

関連する問題