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

如何基于用户输入用NodeJS查询带多WHERE条件的PSQL数据库

解决方案

1. 修改后端接口:支持多类型参数传递

将原路径参数改为查询参数,以便传递多个品类值(用逗号分隔)。修改后的Express接口如下:

app.get('/getInventoryItems', (request, response) => {
    const { types } = request.query;
    if (!types) {
        return response.status(400).json({error: '请指定要查询的品类'});
    }
    // 将逗号分隔的字符串拆分为品类数组
    const typeArray = types.split(',');
    const db = dbService.getDbServiceInstance();
    const result = db.getInventoryItems(typeArray);
    
    result
    .then(data => response.json({data : data}))
    .catch(err => {
        console.log(err);
        response.status(500).json({error: '查询失败'});
    });
})

2. 修改数据库查询方法:动态生成安全的条件语句

使用参数化查询避免SQL注入,用IN替代多个OR(效果一致且代码更简洁):

async getInventoryItems(typeArray) {
    try {
        const response = await new Promise((resolve, reject) => {
            // 为每个品类生成一个占位符,如['tortilla','side']对应'?,?'
            const placeholders = typeArray.map(() => '?').join(',');
            // 构造带IN条件的SQL语句
            const query = `SELECT * FROM cabo_grill WHERE type IN (${placeholders}) AND id > 0 ORDER BY id ASC;`;
            
            connection.query(query, typeArray, (err, results) => {
                if (err)
                    reject(new Error(err.message));
                else
                    resolve(results);
            });
        });
        return response;
    } 
    catch (error) {
        console.log(error);
        throw error; // 抛出错误交由上层接口处理
    }
}

注:type IN ('a','b')与type='a' OR type='b'功能完全等价,前者代码更简洁易维护。

3. 前端修改:处理多选按钮状态并发送请求

假设你的页面上有多个品类按钮(如#proteinBtn、#tortillaBtn),通过维护选中状态集合,实现点击切换并发送动态请求:

// 维护选中的品类集合(自动去重)
const selectedTypes = new Set();

// 给所有品类按钮绑定点击事件
document.querySelectorAll('.category-btn').forEach(btn => {
    btn.addEventListener('click', () => {
        const type = btn.dataset.type; // 假设按钮带有data-type="protein"属性
        // 切换选中状态
        if (selectedTypes.has(type)) {
            selectedTypes.delete(type);
            btn.classList.remove('active');
        } else {
            selectedTypes.add(type);
            btn.classList.add('active');
        }
        // 发送查询请求
        fetchSelectedInventory();
    });
});

// 全选按钮逻辑
document.getElementById('allBtn').addEventListener('click', () => {
    const allTypes = ['protein', 'tortilla', 'side']; // 替换为实际所有品类
    // 切换全选/清空状态
    if (selectedTypes.size === allTypes.length) {
        selectedTypes.clear();
        document.querySelectorAll('.category-btn').forEach(btn => btn.classList.remove('active'));
    } else {
        allTypes.forEach(type => selectedTypes.add(type));
        document.querySelectorAll('.category-btn').forEach(btn => btn.classList.add('active'));
    }
    fetchSelectedInventory();
});

// 根据选中品类发送查询请求
function fetchSelectedInventory() {
    if (selectedTypes.size === 0) {
        // 未选中任何品类时,查询全部数据
        fetchAllInventory();
        return;
    }
    // 将集合转为逗号分隔的字符串
    const typesStr = Array.from(selectedTypes).join(',');
    fetch(`https://project3-7bzcyqo3va-uc.a.run.app/getInventoryItems?types=${typesStr}`) 
    .then(response => response.json())
    .then(data => loadHTMLTable(data['data']))
    .catch(err => console.log(err));
}

// 保留原全量查询函数
function fetchAllInventory() {
    fetch('https://project3-7bzcyqo3va-uc.a.run.app/getAllInventory') 
    .then(response => response.json())
    .then(data => loadHTMLTable(data['data']))
    .catch(err => console.log(err));
}

关键注意事项

  • 防SQL注入:必须使用参数化查询,绝对不能直接将用户输入拼接进SQL语句,上述代码通过占位符+参数数组的方式彻底避免了注入风险。
  • 接口兼容:若需要兼容原有单品类查询,可以保留/getInventoryItem/:type接口,新增/getInventoryItems接口处理多品类场景。
  • 状态管理:使用Set维护选中品类可自动去重,避免重复添加同一品类导致的冗余查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 10:50:24