Nested filters: $filter array, then $filter child array

Since we want to filter both the outer and inner array fields, we can use the $map variable operator which return an array with the "values" we want.

In the $map expression, we provide a logical $conditional $filter to remove the non matching documents from both the document and subdocument array field.

The conditions are $lt which return true when the field "_trashed" is absent in the sub-document and or in the sub-document array field.

Note that in the $cond expression we also return false for the <false case>. Of course we need to apply filter to the $map result to remove all false.

Permit.aggregate(
    [ 
        { "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } },
        { "$project": { 
            "_updated": 1, 
            "_created": 1, 
            "name": 1, 
            "feeClassifications": { 
                "$filter": {
                    "input": {
                        "$map": { 
                            "input": "$feeClassifications", 
                            "as": "fclass", 
                            "in": { 
                                "$cond": [ 
                                    { "$lt": [ "$$fclass._trashed", 0 ] }, 
                                    { 
                                        "_updated": "$$fclass._updated", 
                                        "_created": "$$fclass._created", 
                                        "name": "$$fclass.name", 
                                        "_id": "$$fclass._id", 
                                        "fees": { 
                                            "$filter": { 
                                                "input": "$$fclass.fees", 
                                                "as": "fees", 
                                                "cond": { "$lt": [ "$$fees._trashed", 0 ] }
                                            }
                                        }
                                    }, 
                                    false 
                                ]
                            }
                        }
                    }, 
                    "as": "cls",  
                    "cond": "$$cls"
                }
            }
        }}
    ]
)

In the upcoming MongoDB release (as of this writing and since MongoDB 3.3.5), You can replace the $cond expression in the the $map expression with a $switch expression:

Permit.aggregate(
    [ 
        { "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } },
        { "$project": { 
            "_updated": 1, 
            "_created": 1, 
            "name": 1, 
            "feeClassifications": { 
                "$filter": {
                    "input": {
                        "$map": { 
                            "input": "$feeClassifications", 
                            "as": "fclass", 
                            "in": { 
                                "$switch": { 
                                    "branches": [ 
                                        { 
                                            "case": { "$lt": [ "$$fclass._trashed", 0 ] }, 
                                            "then": { 
                                                "_updated": "$$fclass._updated", 
                                                "_created": "$$fclass._created", 
                                                "name": "$$fclass.name", 
                                                "_id": "$$fclass._id", 
                                                "fees": { 
                                                    "$filter": { 
                                                        "input": "$$fclass.fees", 
                                                        "as": "fees", 
                                                        "cond": { "$lt": [ "$$fees._trashed", 0 ] }
                                                    }
                                                }
                                            } 
                                        } 
                                    ], 
                                    "default":  false 
                                }
                            }
                        }
                    },
                    "as": "cls",  
                    "cond": "$$cls"
                }
            }
        }}
    ]
)