如何将对象键值对推入数组 构建拆分$in项的MongoDB $match查询
问题根因
- 原代码的类型判断逻辑完全失效:
typeof(payload[key])会返回表示数据类型的字符串(比如"number"、"object"),所有非空字符串都是真值,代码永远只会走if分支,根本不会执行$in相关逻辑 - MongoDB的
$in语法使用错误:合法结构为{ 目标字段: { $in: [可选值列表] } },原代码写的{"$in": {[key]: payload[key]}}完全不符合语法规范 - 缺少数组拆分逻辑:针对值为对象数组的字段,没有把数组内对象的键值对拆分为独立的匹配项,导致直接把整个嵌套对象塞进$in的匹配列表里
代码调整方案
直接替换原有逻辑,按以下规则重构:
- 先浅拷贝入参对象,避免直接修改外部传入的原payload
- 用
Array.isArray判断字段值是否为数组,替代失效的typeof判断 - 对数组类型的值做拆分处理:遍历数组内的每个对象元素,将对象的每个键值对拆为独立的小对象,收集为$in的可选值列表
- 严格按照MongoDB语法拼接匹配项
调整后可直接运行的代码:
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.forEach(item => { // 若数组元素为对象,拆分为单键值对的独立匹配项 if (typeof item === 'object' && item !== null) { Object.entries(item).forEach(([subKey, subValue]) => { inMatchList.push({ [subKey]: subValue }) }) } else { inMatchList.push(item) } }) // 按MongoDB语法生成$in匹配规则 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(queryFormat(payload))
运行上述代码即可生成你预期的查询结构:
{ "$match": { "$and": [ {"id": 1}, {"name": "Alfred"}, {"location": "moon"}, {"values": {"$in": [{"name": "u"}, {"age": 9}]}} ] } }
注意:如果数组内的元素不是对象类型,代码会直接把元素本身加入$in的匹配列表,不会做拆分,可兼容普通值数组的查询场景。
内容的提问来源于stack exchange,提问作者AsZik
相关产品推荐
相关产品推荐

