【问题标题】:Mongodb aggregation - geoNear and text search in joined collectionMongodb 聚合 - 连接集合中的 geoNear 和文本搜索
【发布时间】: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 聚合来解决这个问题。问题: 聚合管道阶段 geoNeartext 要求每个阶段都位于管道中的第一位 - 这意味着它们相互排斥。

到目前为止我的想法是:

  1. 开始聚合子,$geoNear 先阶段。这已经切断了 3.5 公里以外的所有餐厅。
  2. $group 按餐厅划分的子公司,并保持每个集群的最小距离值。
  3. $lookup 获取每个集群的匹配餐厅。也许$unwind在这里。
  4. ??? 这里应该是文本/搜索匹配,模糊匹配餐厅的名称。 ???
  5. $match 用于其他值(类别、openingHours、...)
  6. $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


【解决方案1】:

绕过文本搜索和地理查询都必须是第一阶段的要求的一些方法:

  • 使用文本搜索作为第一阶段,然后在后续阶段使用 $set/$expr 手动计算距离。
  • 使用地理查询作为第一阶段,然后在您的应用程序中执行文本过滤(允许您也使用任何您喜欢的文本匹配/相似性算法)。

【讨论】:

  • 关于如何在我的应用中执行文本搜索的任何建议?在这种情况下是否有一个很好的库可以使用?会例如lunrjs 是个不错的选择吗?
  • 这也会导致我必须自己处理分页的问题。但是排序和过滤应该仍然可以保留在聚合中。对吗?
猜你喜欢
  • 2013-04-29
  • 2023-03-21
  • 2018-08-25
  • 1970-01-01
  • 2015-05-29
  • 2015-08-25
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
相关资源
最近更新 更多