Mongoose: how to use aggregate and find together
For MongoDB 3.6 and greater, use the $expr
operator which allows the use of aggregation expressions within the query language:
var followers_count = 30;db.locations.find({ "$expr": { "$and": [ { "$eq": ["$name", "development"] }, { "$gte": [{ "$size": "$followers" }, followers_count ]} ] }});
For non-compatible versions, you can use both the $match
and $redact
pipelines to query your collection. For example, if you want to query the locations
collection where the name is 'development' and followers_count
is greater than 30, run the following aggregate operation:
const followers_count = 30;Locations.aggregate([ { "$match": { "name": "development" } }, { "$redact": { "$cond": [ { "$gte": [ { "$size": "$followers" }, followers_count ] }, "$$KEEP", "$$PRUNE" ] } }]).exec((err, locations) => { if (err) throw err; console.log(locations);})
or within a single pipeline as
Locations.aggregate([ { "$redact": { "$cond": [ { "$and": [ { "$eq": ["$name", "development"] }, { "$gte": [ { "$size": "$followers" }, followers_count ] } ] }, "$$KEEP", "$$PRUNE" ] } }]).exec((err, locations) => { if (err) throw err; console.log(locations);})
The above will return the locations with just the _id
references from the users. To return the users documents as means to "populate" the followers array, you can then append the $lookup
pipeline.
If the underlying Mongo server version is 3.4 and newer, you can run the pipeline as
let followers_count = 30;Locations.aggregate([ { "$match": { "name": "development" } }, { "$redact": { "$cond": [ { "$gte": [ { "$size": "$followers" }, followers_count ] }, "$$KEEP", "$$PRUNE" ] } }, { "$lookup": { "from": "users", "localField": "followers", "foreignField": "_id", "as": "followers" } }]).exec((err, locations) => { if (err) throw err; console.log(locations);})
else you would need to $unwind
the followers array before applying $lookup
and then regroup with $group
pipeline after that:
let followers_count = 30;Locations.aggregate([ { "$match": { "name": "development" } }, { "$redact": { "$cond": [ { "$gte": [ { "$size": "$followers" }, followers_count ] }, "$$KEEP", "$$PRUNE" ] } }, { "$unwind": "$followers" }, { "$lookup": { "from": "users", "localField": "followers", "foreignField": "_id", "as": "follower" } }, { "$unwind": "$follower" }, { "$group": { "_id": "$_id", "created": { "$first": "$created" }, "name": { "$first": "$name" }, "followers": { "$push": "$follower" } } }]).exec((err, locations) => { if (err) throw err; console.log(locations);})
You can use as the following:
db.locations.aggregate([ {$match:{"your find query"}}, {$project:{"your desired fields"}}])
In the match you can do stuff like:
{{$match:{name:"whatever"}}
In the project, you can select the fields you want using numbers 0 or 1 like:
{$project:{_id:1,created:0,name:1}}
Which 0 means, do not put and 1 means put.