web-dev-qa-db-ja.com

MongoDBはSubDocumentを取得します

MongoDBのドキュメントからサブドキュメントを取得したいのですが。私は次の文書を持っています:

{
    "_id" : "10000",
    "password" : "password1",
    "name" : "customer1",
    "enabled" : true,
    "channels" : [ 
        {
            "id" : "10000-1",
            "name" : "cust1chan1",
            "enabled" : true
        }, 
        {
            "id" : "10000-2",
            "name" : "cust1chan2",
            "enabled" : true
        }
    ]
}

私が望む結果は次のとおりです。

{
    "id" : "10000-1",
    "name" : "cust1chan1",
    "enabled" : true
}

ただし、これまでにできる最善の方法は、次のクエリを使用することです。

db.customer.find({"channels.id" : "10000-1"}, {"channels.$" : 1, "_id" : 0})

しかし、これは私に次の結果をもたらします:

{
    "channels" : [ 
        {
            "id" : "10000-1",
            "name" : "cust1chan1",
            "enabled" : true
        }
    ]
}

私の希望する結果が得られるクエリを作成できるかどうか誰かが知っていますか?どんな助けでも大歓迎です。

14
Stuart

AggregationFrameworkでそれを行うことができます。クエリは次のようになります:

db.customer.aggregate([
    {$unwind : "$channels"},
    {$match : {"channels.id" : "10000-1"}},
    {$project : {_id : 0, 
                 id : "$channels.id", 
                 name : "$channels.name", 
                 enabled : "$channels.enabled"}}
])
9

MongoDB 3.4.4以降を使用すると、集約フレームワークは、目的のサブドキュメントを返すために使用できる多数の演算子を提供します。

単一の$replaceRootステージを使用して、フィルター処理されたサブドキュメントをトップレベルにプロモートする集約パイプラインを実行することを検討してください他のすべてのフィールドを置き換えます。

サブドキュメントをフィルタリングするには、$filter演算子が必要です。この演算子は、指定された条件に基づいて返す配列のサブセットを選択します。つまり、条件に一致する要素のみを含む配列を返します。次に、$arrayElemAt演算子を使用して、単一の配列要素をドキュメントに変換できます。

この集計操作を全体的に実行すると、目的の結果が得られます。

db.customer.aggregate([
    { "$replaceRoot": { 
        "newRoot": {
            "$arrayElemAt": [
                { "$filter": {
                   "input": "$channels",
                   "as": "channel",
                   "cond": { /* resolve to a boolean value and determine if an element should be included in the output array. */
                       "$eq": ["$$channel.id", "10000-1"]
                    } 
                } },
                0 /* the element at the specified array index */
            ]
        }
    } }
])

出力

{
    "id" : "10000-1",
    "name" : "cust1chan1",
    "enabled" : true
}
0
chridam