Find documents with arrays that contain a document with a particular field

Deadly 提交于 2019-12-11 00:59:20

问题


I want to find only documents that have all 'docs.foo' present in a array. In my example I should get only _id: 2 result:

{  
    _id : 1,
    docs : [
        { bar : 2},
        { foo : 3, bar : 3}
    ]
},
{  
    _id : 2,
    docs : [
        { foo : 2, bar : 2},
        { foo : 3, bar : 3}
    ]
}

I thought about something like:

db.collection.find({'docs.foo': {$nin: [$exists: false]}})

but couldn't make it work.


回答1:


Using the $where operator.

db.collection.find(function() { 
    return this.docs.length === this.docs.filter(function(doc) {
        return typeof(doc.foo) !== "undefined" && doc.foo !== null ;}).length 
})

Another way to do this is to run two queries: One to retrieve the _id of all those documents that don't match your criteria using the distinct() method:

var unwantedIds = db.collection.distinct( "_id", { "docs": { "$elemMatch": { "foo": { "$exists": false } } } } );

Then use the $nin operator to return all those documents that match your criteria.

db.collection.find({ "_id": { "$nin": unwantedIds } } )

You can also use the .aggregate() method but this only work if you are on version 3.2 or newer because you need to use the $filter

First stage in the pipeline is the $match stage where you filter out those documents where the "foo" field is absent. This reduce the total number of documents that will be processed down the pipe. The next and last stage is the $redact stage. In this stage you need to use the $size operator to return the size of the the "docs" field and the size of the array of the sub-documents in where "foo" is present and return all those documents where the two values are equals.

db.collection.aggregate([
    { "$match": { "docs.foo": { "$exists": true } } }, 
    { "$redact": { 
        "$cond": [ 
            { "$eq": [ 
                { "$size": "$docs" }, 
                { "$size":  { 
                    "$filter": { 
                        "input": "$docs", 
                        "as": "doc", 
                        "cond": { 
                            "$ne": [ 
                                { "$ifNull": [ "$$doc.foo", null ] },
                                null 
                            ] 
                        } 
                    }
                }}
            ]}, 
            "$$KEEP", 
            "$$PRUNE"
        ]
    }}
])


来源:https://stackoverflow.com/questions/35451009/find-documents-with-arrays-that-contain-a-document-with-a-particular-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!