Select sub-documents where field's value is in an some array

后端 未结 2 1499
闹比i
闹比i 2021-01-21 00:46

I want to filter according the sub documents, but actually I am repeating the document for each sub document. I want one document and a list of sub documents if that is the case

相关标签:
2条回答
  • 2021-01-21 01:32

    First of all using the $unwind operator as mentioned in this answer will cause a drop of performance in your application because unwinding your array result in more documents to process down in the pipeline. There is a better way to achieve this since MongoDB 2.6.

    That being said, this is a perfect job for the $filter operator new in MongoDB 3.2.

    The most efficient way to do this is in MongoDB 3.4. MongoDB 3.4 introduced the $in array operator for the aggregation framework which can be used in the $filter conditional expression which, when evaluates to true include the sub-document in the resulting array.

    let values = [ '000', '011' ];
    
    db.collection.aggregate([ 
        { "$project": { 
            "filename": 1, 
            "cod": 1, 
            "subdocs": { 
                "$filter": { 
                    "input": "$subdocs", 
                    "as": "s", 
                    "cond": { "$in": [ "$$s.desc", values ] }
                } 
            } 
        }} 
    ])
    

    In MongoDB 3.2 we need a slightly different approach because we can use the $in operator there. But luckily we have the $setIsSubset operator and as you might have guess performs a set operation on two array and return true if the first array is a subset of the second array. Because $setIsSubset first expression must be an array, need to make the desc field an array in our pipeline. To do this, we simply use the [] bracket the create that array field which is new MongoDB 3.2

    db.collection.aggregate([ 
        { "$project": { 
            "filename": 1, 
            "cod": 1, 
            "subdocs": { 
                "$filter": { 
                    "input": "$subdocs", 
                    "as": "s", 
                    "cond": { "$setIsSubset": [ [ "$$s.desc" ], values ] }
                } 
            } 
        }} 
    ])
    

    MongoDB 3.0 is dead to me but if for some reasons you are running that version, you can use the $literal operator to return the one element array you need for the set operation and the $setDifference operator. This is left as exercise to the reader.

    0 讨论(0)
  • 2021-01-21 01:39

    You just need to add $group & $push. First you $unwind the subdocs to apply the $match followed by $group on id and $push the grouped subdocs.

    db.ftmp.aggregate({
        $unwind: "$subdocs"
    }, {
        $match: {
            "subdocs.desc": {
                $in: ["000", "011"]
            }
        }
    }, {
        $group: {
            _id: "$_id",
            subdocs: {
                $push: "$subdocs"
            },
            filename: {
                $first: "$filename"
            },
            cod: {
                $first: "$cod"
            }
        }
    })
    
    0 讨论(0)
提交回复
热议问题