我正在编写一个Mongo查询生成器,我在文档中发现了两个语句:
(文本搜索)包含$ Text的$match阶段必须是管道中的第一阶段。
(地理搜索)你只能使用$geoNear作为管道的第一阶段。
意思是一样的,所以…如何一起使用它们?
我知道这是一个老问题,但我最近有一个类似的问题,所以我想我应该张贴我的解决方案。
在我的例子中,我想:
- 首先在用户提供的关键字上使用全文搜索作为过滤器
- 然后,根据与用户提供的坐标的距离对结果进行排序
- 用户可以选择提供关键词、位置或两者都提供(困难的情况)
我用这样一段代码来处理它:
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)
基本上,如果文本搜索或地理搜索本身需要,则构建适当的查询没有问题。如果两者都需要,则首先执行文本查询,然后将返回的文档id作为过滤器传递给第二个。
这是我能找到的性能最好的解决方案!
我认为你做不到。我过去做过的一件事是执行查询并将结果合并到应用程序代码中。
您可以创建一个$match聚合阶段,并使用$geoWithin(或$geoIntersect)和$text操作符。那似乎是最好的解决办法。
MongoDB Atlas Search还允许同时过滤全文和位置