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默认基于字节比对,不会自动将无重音字符映射为带重音字符。规范化字符串重音:
- 编写去重音工具函数:
function removeAccents(str) { return str.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); } - 用聚合管道同时处理数据库字段与搜索词:
该方法通过const producto = await Producto.aggregate([ { $addFields: { titleNormalized: { $normalize: { input: "$title", form: "NFKD" } } } }, { $match: { titleNormalized: { $regex: removeAccents(searchWords), $options: "i" } } } ]);$normalize将数据库中带重音的标题转为无重音形式,同时对搜索词做去重音处理,再进行正则匹配。
- 编写去重音工具函数:
使用带collation的文本索引:
- 给
title字段创建带指定collation的文本索引:ProductoSchema.index({ title: "text" }, { collation: { locale: "es", strength: 2 } }); - 改用文本搜索查询:
文本搜索会遵循索引的collation规则,自动忽略重音差异,实现“arnes”匹配“arnés”的需求。const producto = await Producto.find( { $text: { $search: searchWords } }, { score: { $meta: "textScore" } } ) .collation({ locale: "es", strength: 2 }) .sort({ score: { $meta: "textScore" } });
- 给
全局设置Schema的collation:在定义Schema时直接指定collation,确保所有查询默认遵循该规则:
const ProductoSchema = new mongoose.Schema({ title: String, // 其他字段定义 }, { collation: { locale: "es", strength: 2 } });
内容的提问来源于stack exchange,提问作者ddaudiosolutions
相关产品推荐
相关产品推荐

