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

URL查询优化最佳实践咨询:模糊匹配实现与URL编码问题

电影筛选功能问题与解决

场景与代码

我正在实现一个电影筛选功能,前端通过硬编码拼接URL查询参数获取DOM值,后端用MongoDB处理查询,但遇到了两个问题。相关代码如下:

前端代码(Client-Side-js.js)

async function filterMovie(e){
    try {
        const queryAddon = `?title=${titleDOM.value}&genre=${genreDOM.value}&publishDateDOM=${publishDateDOM.value}&limit=${limitDOM.value}&skip=${skipDOM.value}&sort=${sortDOM.value}`
        let data = await fetch(`${baseURL}/movie/filter${queryAddon}`);
        data = await data.json();
        console.log(data);
    } catch (error) {
        console.log(error)

    }
}

后端代码(movie-controller.js)

const showOneMovie = async(req,res)=>{
    try {
        const {title, publishDate, genre, limit, skip, sort} = req.query;
        let data = await Movie.find({title, publishDate, genre}).limit(limit).skip(skip).sort(sort)
        res.status(200).json(data);
    } catch (error) {
        console.log(error)
    }
}

问题

  1. 当前过滤器仅支持精确匹配,无法实现前缀匹配(startsWith)、包含匹配或多值匹配(in),请问最佳实践和实现方式是什么?
  2. 听说URL需要编码,直接拼接字符串会有什么问题?本例中该如何处理编码?

解决方案

问题1:实现模糊/多值匹配

要实现非精确匹配,需要在后端动态构造MongoDB查询条件,不能直接将参数传入find方法。以下是不同匹配方式的实现:

1. 前缀匹配(startsWith,忽略大小写)

使用MongoDB的$regex配合^锚点,确保只匹配以输入值开头的记录:

query.title = { $regex: new RegExp(`^${title}`, 'i') };

'i'表示忽略大小写,比如输入"star"能匹配"Star Wars"和"Star Trek"。

2. 包含匹配

去掉^锚点即可实现包含匹配:

query.title = { $regex: title, 'i' };

3. 多值匹配(in)

如果参数是逗号分隔的多个值(比如genre=action,comedy),先将参数拆分为数组,再用$in操作符:

const genreList = genre.split(',');
query.genre = { $in: genreList };

修改后的后端完整代码

const showOneMovie = async(req,res)=>{
    try {
        const {title, publishDate, genre, limit, skip, sort} = req.query;
        const query = {};

        // 处理标题前缀匹配
        if(title){
            query.title = { $regex: new RegExp(`^${title}`, 'i') };
        }

        // 处理日期前缀匹配(比如匹配年份)
        if(publishDate){
            query.publishDate = { $regex: new RegExp(`^${publishDate}`) };
        }

        // 处理多类型匹配
        if(genre){
            const genreList = genre.split(',');
            query.genre = { $in: genreList };
        }

        // 处理分页参数,默认值防止报错
        const queryLimit = parseInt(limit) || 10;
        const querySkip = parseInt(skip) || 0;

        let data = await Movie.find(query).limit(queryLimit).skip(querySkip).sort(sort);
        res.status(200).json(data);
    } catch (error) {
        console.log(error);
        res.status(500).json({error: '服务器内部错误'});
    }
}

问题2:URL编码处理

直接拼接的问题

  • 破坏URL结构:如果参数包含空格、&、=等特殊字符,会导致URL解析错误。比如电影名是"Star Wars",直接拼接会变成?title=Star Wars,后端只能拿到title=Star,后续内容会被截断。
  • 中文乱码:中文在不同编码环境下会出现乱码,后端无法正确解析。

正确的编码方式

推荐使用URLSearchParams自动处理编码和参数格式,它会自动对每个参数值编码,还能过滤空参数(未填写的参数不会加入URL)。修改后的前端代码:

async function filterMovie(e){
    try {
        // 注意:修正了参数名错误(publishDateDOM → publishDate,和后端对应)
        const queryParams = new URLSearchParams({
            title: titleDOM.value,
            genre: genreDOM.value,
            publishDate: publishDateDOM.value,
            limit: limitDOM.value,
            skip: skipDOM.value,
            sort: sortDOM.value
        });

        let data = await fetch(`${baseURL}/movie/filter?${queryParams}`);
        data = await data.json();
        console.log(data);
    } catch (error) {
        console.log(error);
    }
}

如果一定要手动编码,可以用encodeURIComponent()对每个参数值单独处理:

const queryAddon = `?title=${encodeURIComponent(titleDOM.value)}&genre=${encodeURIComponent(genreDOM.value)}&publishDate=${encodeURIComponent(publishDateDOM.value)}&limit=${encodeURIComponent(limitDOM.value)}&skip=${encodeURIComponent(skipDOM.value)}&sort=${encodeURIComponent(sortDOM.value)}`;

但URLSearchParams更简洁可靠,优先推荐。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:22:20