You need to enable JavaScript to run this app. 如何将键值对推入数组构建MongoDB动态查询并拆分$in数组条件
优惠活动
大模型
产品
解决方案
定价
更多

如何将键值对推入数组构建MongoDB动态查询并拆分$in数组条件

核心问题定位

原代码无法生成预期查询结构,主要存在3处逻辑错误:

  • 类型判断逻辑完全失效:if(typeof(payload[key])) 写法永远为真,因为typeof 对非undefined 的值会返回非空的类型字符串(如"number"、"string"),属于truthy值,导致永远无法触发else分支的特殊处理逻辑。
  • 数组类型字段未做适配:遇到数组类字段(如示例中的values),代码直接将原数组整体作为字段值推入查询条件,既没有按照MongoDB语法构造$in 查询结构,也没有将数组内的复合对象拆分为单键匹配元素。
  • 特殊分支的查询结构错误:即使进入else分支,原代码将$in 放在条件对象的顶层,写法完全不符合MongoDB查询规范,正确结构应为{ 字段名: { "$in": 匹配值列表 } }。
调整方案

遍历payload的键值对时按值的类型做分支处理:

  • 字段值为非数组类型时,直接将键值对作为普通查询条件推入结果数组。
  • 字段值为数组类型时,先将数组内的复合对象拆分为单键组成的匹配列表,再构造标准的$in 查询结构推入结果数组。
调整后可运行代码
const queryFormat = (payload) => {
    // 浅拷贝避免直接修改传入的原对象
    const targetPayload = { ...payload }
    delete targetPayload.userEventId

    const query = {}
    const res = []

    for (const key in targetPayload) {
        const value = targetPayload[key]
        if (Array.isArray(value)) {
            // 拆解数组内的复合对象为单键匹配项
            const inMatchList = value.flatMap(item => 
                Object.entries(item).map(([k, v]) => ({ [k]: v }))
            )
            res.push({ [key]: { "$in": inMatchList } })
        } else {
            res.push({ [key]: value })
        }
    }

    query['$match'] = { "$and": res }
    return query
}

const payload = {
    id: 1,
    name: 'Alfred',
    location: 'moon',
    values: [{ name: 'u', age: 9 }]
}

// 运行输出与预期结构完全一致
console.log(JSON.stringify(queryFormat(payload)))
运行输出结果
{"$match":{"$and":[{"id":1},{"name":"Alfred"},{"location":"moon"},{"values":{"$in":[{"name":"u"},{"age":9}]}}]}}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 18:27:08