Använda $where
operatör.
db.collection.find(function() {
return this.docs.length === this.docs.filter(function(doc) {
return typeof(doc.foo) !== "undefined" && doc.foo !== null ;}).length
})
Ett annat sätt att göra detta är att köra två frågor:En för att hämta _id
av alla de dokument som inte matchar dina kriterier med distinct()
metod:
var unwantedIds = db.collection.distinct( "_id", { "docs": { "$elemMatch": { "foo": { "$exists": false } } } } );
Använd sedan $nin
operatör för att returnera alla de dokument som matchar dina kriterier.
db.collection.find({ "_id": { "$nin": unwantedIds } } )
Du kan också använda
code>.aggregate()
metod men detta fungerar bara om du har version 3.2 eller senare eftersom du behöver använda $filter
Första steget i pipelinen är $match
steg där du filtrerar bort de dokument där "foo"-fältet saknas. Detta minskar det totala antalet dokument som kommer att behandlas. Nästa och sista steg är $redact
skede. I det här skedet måste du använda $size
operatör för att returnera storleken på fältet "dokument" och storleken på arrayen av underdokument där "foo" finns och returnera alla de dokument där de två värdena är lika.
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"
]
}}
])