I know this is an old question but I've recently had a similar problem so I thought I'd post my solution.
In my case I wanted:
- first to use full-text search on user-supplied keywords as a filter
- then, sort the results by distance from user-supplied coordinates
- user could choose to provide keywords, location or both (the difficult case)
I tackled it with a block of code like this:
let query = {}
if(req.query.keywords){
if(req.query.lng || req.query.lat){
db.collection("service")
.find({ $text: { $search: req.query.keywords }})
.toArray()
.then(docs => query._id = { $in: docs.map(doc => doc._id) })
} else {
query.$text = { $search: req.query.keywords }
}
}
if(req.query.lat && req.query.lng){
query.location = {
$nearSphere: {
$geometry: {
type: "Point",
coordinates: [req.query.lng, req.query.lat]
}
}
}
}
db.collection("service").find(query)
Basically if a text search or a geo search is desired by itself, the appropriate query is built no problem. If both are needed, it does a text query first, and then passes the returned document ids as a filter to the second.
This is the most performant solution I could find!