sql >> データベース >  >> NoSQL >> MongoDB

Mongoアグリゲーションでドキュメントの配列フィールドをマージする方法

    TLDR;

    最新のリリースでは、$reduceを使用する必要があります $setUnionを使用 最初の$groupの後 示されているように:

    db.collection.aggregate([
      { "$group": {
        "_id": { "Host": "$Host", "ArtId": "$ArtId" },
        "count": { "$sum": 1 },
        "tags": { "$addToSet": "$tags" }
      }},
      { "$addFields": {
        "tags": {
          "$reduce": {
            "input": "$tags",
            "initialValue": [],
            "in": { "$setUnion": [ "$$value", "$$this" ] }
          }
        }
      }}
    ])
    

    あなたは$addToSetを見つけるのに正しかった 演算子ですが、配列内のコンテンツを操作する場合は、通常、 $unwindで処理する必要があります 最初。これにより、配列エントリが「非正規化」され、基本的に、各配列エントリがフィールド内の特異値として親ドキュメントの「コピー」が作成されます。それはあなたがそれを使わずにあなたが見ている行動を避けるためにあなたが必要とするものです。

    あなたの「カウント」は興味深い問題を引き起こしますが、最初の $groupの後に「ダブルアンワインド」を使用することで簡単に解決できます 操作:

    db.collection.aggregate([
        // Group on the compound key and get the occurrences first
        { "$group": {
            "_id": { "Host": "$Host", "ArtId": "$ArtId" },
            "tcount": { "$sum": 1 },
            "ttags": { "$push": "$tags" }
        }},
    
        // Unwind twice because "ttags" is now an array of arrays
        { "$unwind": "$ttags" },
        { "$unwind": "$ttags" },
    
        // Now use $addToSet to get the distinct values        
        { "$group": {
            "_id": "$_id",
            "tcount": { "$first": "$tcount" },
            "tags": { "$addToSet": "$ttags" }
        }},
    
        // Optionally $project to get the fields out of the _id key
        { "$project": {
            "_id": 0,
            "Host": "$_id.Host",
            "ArtId": "$_id.ArtId",
            "count": "$tcount",
            "tags": "$ttags"
        }}
    ])
    

    $projectの最後のビット また、集計パイプラインの他のステージの各フィールドに「一時的な」名前を使用したためです。これは、 $projectに最適化があるためです。 これは、既存のステージのフィールドを、「新しい」フィールドがドキュメントに追加される「前」にすでに表示されている順序で「コピー」します。

    それ以外の場合、出力は次のようになります。

    {  "count":2 , "tags":[ "tag1", "tag2", "tag3" ], "Host": "abc.com", "ArtId": "123" }
    

    フィールドがあなたが思うかもしれないのと同じ順序ではないところ。些細なことですが、一部の人にとっては重要なので、その理由と処理方法を説明する価値があります。

    つまり、 $unwind アイテムを配列ではなく分離して保持する作業を行い、 $groupを実行します 最初に、「グループ化」キーの発生の「カウント」を取得できます。

    $first 演算子は、「タグ」配列に存在するすべての値に対して「複製」されたため、後でその「カウント」値を「保持」します。とにかくそれはすべて同じ値なので、それは問題ではありません。 1つ選んでください。




    1. redisリスナーの作成-phpで可能ですか?

    2. MongoDB mapreduceで、valuesオブジェクトをフラット化するにはどうすればよいですか?

    3. データベースクラスター全体でのメンテナンスウィンドウの簡単なスケジューリング

    4. MongoDBインスタンスまたはレプリカセットのクローン作成