猫鼬全文搜索未正确过滤

时间:2020-04-29 16:03:40

标签: node.js mongodb express mongoose

因此,基本上我的模型具有一堆字符串字段,如下所示:

const Schema: Schema = new Schema(
  {
    title: {
      type: String,
      trim: true
    },
    description: {
      type: String,
      trim: true
    },
    ...
  }
);

Schema.index({ '$**': 'text' });

export default mongoose.model('Watch', Schema);

我将所有索引都编入索引。

现在,当我搜索该模式用作其他模型的引用时,我会像这样进行搜索,其中user是另一个模型的实例

  const { search, limit = 5 } = req.query;
  const query = search && { match: { $text: { $search: new RegExp(search, 'i') } } };

  const { schemaRes } = await user
    .populate({
      path: 'schema',
      ...query,
      options: {
        limit
      }
    })
    .execPopulate();

并且搜索本身似乎可以正常工作,问题是当搜索字段开始更加具体时,在我看来,它并不满意。

示例 db

  { title: 'Rolex', name: 'Submariner', description: 'Nice' }
  { title: 'Rolex', name: 'Air-King', description: 'Nice' }

当搜索参数为Rolex时,我会得到两个都可以的商品,但是当搜索参数变为Rolex Air-King时,我会继续获取对我来说都不好的两个商品,因为我宁愿只得到一个

我可以做些什么吗?

1 个答案:

答案 0 :(得分:0)

返回两个项目都是正确的,因为这两个项目都符合您的搜索参数,但相似度得分不同。

您可以输出相似度分数以帮助对结果进行排序。

user.aggregate([
  { $match: { $text: { $search: "Rolex Air-King" } } },
  { $set: {  score: { $meta: "textScore" } } }
])
// new RegExp("Rolex Air-King", 'i') is not necessary and even invalid,
// as $search accepts string and is already case-insensitive by default

查询将返回

[{
  "_id": "...",
  "title": "Rolex",
  "name": "Air-King",
  "description": "Nice",
  "score": 2.6
},
{
  "_id": "....",
  "title": "Rolex",
  "name": "Submariner",
  "description": "Nice",
  "score": 1.1
}]

由于第二个结果项匹配您的搜索查询(甚至部分匹配),因此MongoDB会返回它。

您可以使用分数来帮助对项目进行排序。但是确定正确的阈值以过滤结果很复杂,因为分数也取决于单词数。

注意:如果字段的重要性不同,则可以为它们分配不同的权重 https://docs.mongodb.com/manual/tutorial/control-results-of-text-search/