1

次のようなデータセットがあります。

{
  "id": "02741544",
  "items": [{
    "item": "A"
  }]
}, {
  "id": "02472691",
  "items": [{
    "item": "A"
  }, {
    "item": "B"
  }, {
    "item": "C"
  }]
}, {

  "id": "01316523",
  "items": [{
    "item": "A"
  }, {
    "item": "B"
  }]
}, {
  "id": "01316526",
  "items": [{
    "item": "A"
  }, {
    "item": "B"
  }]
}, {
  "id": "01316529",
  "items": [{
    "item": "A"
  }, {
    "item": "D"
  }]
},

次のような出力が得られるクエリを作成しようとしています。

{
  "item": "A",
  "ids": [{
    "id": "02741544"

  }, {
    "id": "02472691"

  }, {
    "id": "01316523"

  }, {
    "id": "01316526"

  }, {
    "id": "01316529"

  }]
}, {
  "item": "B",
  "ids": [{
    "id": "02472691"

  }, {
    "id": "01316523"

  }, {
    "id": "01316526"

  }]
}, {
  "item": "C",
  "ids": [{
    "id": "02472691"

  }]
}, {
  "item": "D",
  "ids": [{
    "id": "02472691"

  }]
},

基本的に、オブジェクトのアイテム配列から個別のアイテムを取得しようとしており、アイテム配列にそのアイテムを持つ各 obj の ID の配列を返します。

4

2 に答える 2

2

次のパイプライン ステップ (指定された順序) で構成される操作を実行する必要がある集計フレームワークを使用することをお勧めします。

  1. $unwind- この最初のステップは、配列を平坦化しitemsます。つまり、配列エントリごとに各ドキュメントのコピーを作成します。これは、ドキュメントをグループとして集約できる「非正規化」ドキュメントとして処理するために必要です。
  2. $group- これにより、フラット化されたドキュメントがitemサブドキュメント キーでグループ化され、 accumulator 演算子idsを使用してリストが作成されます。$push

- アップデート -

@AminJ がコメントで指摘したように、itemsアイテムの値が重複する可能性があり、結果に重複した ID を使用したくない場合は、$addToSet代わりに使用できます$push

次の例は、これを示しています。

db.collection.aggregate([   
    { "$unwind": "$items" },
    {
        "$group": {
            "_id": "$items.item",
            "ids": { 
                "$push": { "id": "$id" } /* or use 
                "$addToSet": { "id": "$id" } if you don't want duplicate ids */                    
            }
        }
    }
])

サンプル出力

{
    "_id" : "A",
    "ids" : [ 
        { "id" : "02741544" }, 
        { "id" : "02472691" }, 
        { "id" : "01316523" }, 
        { "id" : "01316526" }, 
        { "id" : "01316529" }
    ]
}

/* 2 */
{
    "_id" : "B",
    "ids" : [ 
        { "id" : "02472691" }, 
        { "id" : "01316523" }, 
        { "id" : "01316526" }
    ]
}

/* 3 */
{
    "_id" : "C",
    "ids" : [ 
        { "id" : "02472691" }
    ]
}

/* 4 */
{
    "_id" : "D",
    "ids" : [ 
        { "id" : "01316529" }
    ]
}

関数の結果aggregate()は、集約パイプライン操作の最終段階で生成されたドキュメントへのカーソルです。したがって、結果を配列で取得したい場合は、カーソルのtoArray()メソッドを使用して、そこからすべてのドキュメントを含む配列を返すことができます。

例えば:

var pipeline = [    
        { "$unwind": "$items" },
        {
            "$group": {
                "_id": "$items.item",
                "ids": { 
                    "$push": { "id": "$id" } /* or use 
                    "$addToSet": { "id": "$id" } if you don't want duplicate ids */                    
                }
            }
        }
    ],
    results = db.collection.aggregate(pipeline).toArray();

printjson(results);
于 2016-09-23T15:15:51.567 に答える
0

集計パイプラインを使用したソリューションを次に示します。

    db.col.aggregate([
        {
            $unwind: "$items"
        },
        {
            $project: {
                id: 1,
                item: "$items.item"
            }
        },
        {
            $group: {
                _id: "$item",
                ids: {
                    $push: "$id"
                }
            }
        }
    ])
于 2016-09-23T15:15:52.727 に答える