You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MongoDB $text搜索中忽略关键词重复并优化排序?

解决MongoDB $text搜索关键词重复刷分及结合_id时间排序的问题

核心思路

要解决关键词重复刷分问题,需要放弃默认的textScore(基于词频计算),改用自定义评分逻辑——仅判断关键词是否出现(而非出现次数),同时将_id的时间戳纳入评分,让最新文章获得额外权重。

具体实现步骤

1. 保留原text索引(用于高效过滤)

原有的text索引继续保留,用来快速筛选包含目标关键词的文档,避免全表扫描:

db.articles.createIndex(
  { title: "text", content: "text" },
  { weights: { title: 10, content: 1 } }
)

2. 使用聚合管道实现自定义评分与排序

通过聚合管道完成「过滤→计算自定义得分→排序」的流程:

db.articles.aggregate([
  // 第一步:用text索引快速过滤匹配关键词的文档
  { $match: { $text: { $search: "New York" } } },

  // 第二步:计算各维度得分
  {
    $addFields: {
      // 标题匹配得10分(仅判断是否包含,忽略次数)
      titleScore: {
        $cond: {
          if: { $regexMatch: { input: "$title", regex: "New York", options: "i" } },
          then: 10,
          else: 0
        }
      },
      // 内容匹配得1分(仅判断是否包含,忽略次数)
      contentScore: {
        $cond: {
          if: { $regexMatch: { input: "$content", regex: "New York", options: "i" } },
          then: 1,
          else: 0
        }
      },
      // 从_id提取时间戳(转成秒级数值,用于时间权重计算)
      timeScore: { $divide: [ { $toLong: { $toDate: "$_id" } }, 1000000000 ] }
    }
  },

  // 第三步:计算总得分(时间权重系数可根据需求调整)
  {
    $addFields: {
      customScore: {
        $add: [
          "$titleScore",
          "$contentScore",
          { $multiply: [ "$timeScore", 0.01 ] } // 时间系数:避免盖过内容/标题的权重
        ]
      }
    }
  },

  // 第四步:按自定义得分倒序,得分相同则按_id倒序(最新文章在前)
  { $sort: { customScore: -1, _id: -1 } },

  // 可选:清理中间计算字段
  { $project: { titleScore: 0, contentScore: 0, timeScore: 0 } }
])

关键细节说明

  • 忽略关键词重复:通过$regexMatch仅判断字段是否包含关键词,无论出现多少次都只加固定分数,彻底杜绝刷分行为。
  • 时间权重调整:timeScore的系数(示例中为0.01)可根据业务需求调整——如果希望时间因素影响更大,可适当提高系数(如0.1);反之则调小。
  • 性能保障:先用$text过滤文档,再对少量匹配结果执行$regexMatch,避免全表扫描导致的性能问题。

内容的提问来源于stack exchange,提问作者hskris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 03:15:58