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

后端 未结 2 1521
闹比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.

提交回复
热议问题