web-dev-qa-db-ja.com

$ projectステージで$ in演算子を使用して配列をフィルタリングします

現在、 $ filter 配列集計演算子で $ in 演算子を使用することはできません。

これがドキュメントスキーマであるとしましょう:

{
    _id: 1,
    users: [
        {
            _id: 'a',
            accounts: ['x', 'y', 'z']
        },
        {
            _id: 'b',
            accounts: ['j','k','l']
        }
    ]
}

aggregateを使用して、users配列の内容に基づいてaccountsのフィルター処理された配列を持つドキュメントを取得したいと思います。

[〜#〜] if [〜#〜]$in$filter演算子で機能する場合、次のようになります。

db.test.aggregate([
    {
        $project: {
            'filtered_users': {
                $filter: {
                    input: '$users',
                    as: 'user',
                    cond: {
                        $in: ['$$user.accounts', ['x']]
                    }
                }
            }
        }
    }
])

xinのアカウントであるため、最初のユーザーのみをfiltered_usersに返します。

しかし、私が言ったように、これは機能せず、エラーが発生します:

"無効な演算子 '$ in'"

$filter演算子ではサポートされていないためです。

これで、$unwindと通常の$match演算子を使用してそれを実行できることがわかりましたが、結果を元に戻すために$groupを使用する必要があるため、集計がはるかに長く(そして醜く)なります。配列として-これは必要ありません

私の質問は、$filter演算子を操作して目的の結果を得る他の方法があるかどうかです。

10
TomG

$inは配列の集約操作ではサポートされていないため、代わりに$setIsSubsetを使用することもできます。詳細については、 this linkを参照してください。集計クエリは次のようになります

db.test.aggregate([
{
    $project: {
        'filtered_users': {
            $filter: {
                input: '$users',
                as: 'user',
                cond: {
                   $setIsSubset: [['x'], '$$user.accounts']           
                }
            }
        }
    }
}])

このクエリは、[x]の配列のサブセットとしてuser.accountsを持つ要素のみを返します。

15
Ananth Pai

MongoDB 3.4以降では、 $in$project ステージ

db.collection.aggregate([     
    {         
        "$project": {             
            "filtered_users": {                 
                "$filter": {                     
                    "input": "$users",                     
                    "as": "user",                     
                    "cond": { "$in": [ "x", "$$user.accounts" ] }                     
                }  
            }         
        }     
    } 
])
11
styvane