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

MongoDB集合变音符号不敏感搜索问题求助

问题描述

我在Node.js中有如下代码,用于接收搜索词并查询Producto集合:

exports.findProductsByWords = async (req, res) => {
  let searchWords = req.body.searchWord; // Replace with your array of words
  console.log("searchWords", searchWords);

  try {
    const producto = await Producto.find({
      title: { $regex: searchWords, $options: "i" },
    }).collation({ locale: "es", strength: 2 });
    /* .populate({
        path: "author",
        select: "nombre direccion telefono email imagesAvatar",
      }); */
    console.log("el producto :" + producto);
    res.status(200).json({ prodAll: producto });
  } catch (error) {
    console.log(error);
    res.status(500).send("Hubo un Error");
  }
};

需求是:无论搜索框输入“arnés”还是“arnes”,都能查询到数据库中标题含“arnés”的产品。尝试用collation实现但未生效,数据库存储的标题均为“arnés”,使用Mongoose 7.5.0版本。

解决思路
  • 明确collation对$regex的限制:MongoDB的collation参数中strength:2仅在排序、相等匹配场景下忽略重音,对$regex的部分字符串匹配不生效——$regex默认基于字节比对,不会自动将无重音字符映射为带重音字符。

  • 规范化字符串重音:

    1. 编写去重音工具函数:
      function removeAccents(str) {
        return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
      }
      
    2. 用聚合管道同时处理数据库字段与搜索词:
      const producto = await Producto.aggregate([
        {
          $addFields: {
            titleNormalized: {
              $normalize: { input: "$title", form: "NFKD" }
            }
          }
        },
        {
          $match: {
            titleNormalized: { $regex: removeAccents(searchWords), $options: "i" }
          }
        }
      ]);
      
      该方法通过$normalize将数据库中带重音的标题转为无重音形式,同时对搜索词做去重音处理,再进行正则匹配。
  • 使用带collation的文本索引:

    1. 给title字段创建带指定collation的文本索引:
      ProductoSchema.index({ title: "text" }, { collation: { locale: "es", strength: 2 } });
      
    2. 改用文本搜索查询:
      const producto = await Producto.find(
        { $text: { $search: searchWords } },
        { score: { $meta: "textScore" } }
      )
      .collation({ locale: "es", strength: 2 })
      .sort({ score: { $meta: "textScore" } });
      
      文本搜索会遵循索引的collation规则,自动忽略重音差异,实现“arnes”匹配“arnés”的需求。
  • 全局设置Schema的collation:在定义Schema时直接指定collation,确保所有查询默认遵循该规则:

    const ProductoSchema = new mongoose.Schema({
      title: String,
      // 其他字段定义
    }, { collation: { locale: "es", strength: 2 } });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 06:13:35