【发布时间】:2020-12-26 09:51:12
【问题描述】:
我有一个棘手的查询,它触及了我的 MongoDB 专业知识。这里是简化的场景。
我们有一个集合Restaurant 和一个集合Subsidary。
它们看起来大致像这样(简化 - 使用猫鼬):
const restaurantSchema = new Schema(
{
name: { type: String, required: true },
categories: { type: [String], required: true },
...
})
const subsidarySchema = new Schema(
{
restaurant: { type: Schema.Types.ObjectId, ref: 'Restaurant' },
location: {
type: { type: String, enum: ['Point'], required: true },
coordinates: { type: [Number], required: true },
},
...
})
需要什么:
- 始终:查找在半径 3.5 公里范围内设有分店的餐厅并按距离排序。
- 有时还会通过与餐厅名称模糊匹配的字符串过滤这些餐厅。
- 应用更多过滤器和分页(例如按类别过滤,...)
我正在尝试使用 mongodb 聚合来解决这个问题。问题:
聚合管道阶段 geoNear 和 text 要求每个阶段都位于管道中的第一位 - 这意味着它们相互排斥。
到目前为止我的想法是:
- 开始聚合子,
$geoNear先阶段。这已经切断了 3.5 公里以外的所有餐厅。 -
$group按餐厅划分的子公司,并保持每个集群的最小距离值。 -
$lookup获取每个集群的匹配餐厅。也许$unwind在这里。 - ??? 这里应该是文本/搜索匹配,模糊匹配餐厅的名称。 ???
-
$match用于其他值(类别、openingHours、...) -
$sort和$limit和$skip用于排序和分页。
这里同插图。
问题
- 这种方法有意义吗?实施第 4 阶段的可能方法是什么?
- 我搜索了很多,但似乎没有办法使用像
{ $match: { $text: { $search: req.query.name } } }这样的东西作为第四阶段。 - 另一种方法是在处理文本搜索之前运行第二个查询,然后构建一个交集。这可能会导致在该阶段传递大量餐厅 ID。这是 mongodb 可以处理的吗?
非常感谢你们的cmets!
【问题讨论】:
-
$text 可能不会按照您想要的方式进行模糊搜索。例如,如果文档中的名称是“Blueberry Barn”,则搜索“blueberries”和“bARN”将匹配,但搜索“Blue”、“berry”和“bar”将不匹配。
-
公平点!但我可能可以使用新的
$search舞台——显然只有Atlas 才有。 mongodb.com/atlas/search
标签: node.js mongodb mongoose mongodb-query