如何在Mongoose的$and查询语句中动态嵌套$or操作符
现有代码的核心问题
- 字段映射错误:GraphQL入参的过滤字段是
titles,但MongoDB集合中对应的存储字段是title,直接用入参的key作为查询字段无法匹配到数据。 - 对象引用重复问题:你在
map循环外声明了sObj,每次循环修改的都是同一个对象的属性,最终sObjArray中所有元素都会指向最后一次赋值的对象,导致$or条件失效。另外你预期的MongoDB查询写法也有语法错误,同一个对象中重复声明title属性会发生覆盖,正确的$or写法应该是{$or: [{title:"Fast Five"}, {title:"Jumanji"}]}。
修复实现(推荐用$in简化逻辑)
多值匹配用$in操作符和手动拼接$or的查询效果完全一致,代码更简洁易维护:
getMovies: async args => { try{ const inputFilter = args.itemFilterInput; const filters = []; // 字段映射表:GraphQL入参字段名 -> MongoDB存储字段名 const fieldMap = { titles: 'title', rating: 'rating' }; Object.keys(inputFilter).forEach(inputKey => { const mongoField = fieldMap[inputKey]; const value = inputFilter[inputKey]; if(Array.isArray(value)){ filters.push({ [mongoField]: { $in: value } }); } else { filters.push({ [mongoField]: value }); } }); const items = await Item.find({ $and: filters }); return items; } catch (err) { throw err; } }
严格符合你预期的$or格式实现
如果你一定要生成$or嵌套的查询结构,可以用下面的写法,解决了对象引用重复的问题:
getMovies: async args => { try{ const inputFilter = args.itemFilterInput; const filters = []; const fieldMap = { titles: 'title', rating: 'rating' }; Object.keys(inputFilter).forEach(inputKey => { const mongoField = fieldMap[inputKey]; const value = inputFilter[inputKey]; if(Array.isArray(value)){ // 每次循环生成新对象,避免引用重复 const orConditions = value.map(prop => ({ [mongoField]: prop })); filters.push({ $or: orConditions }); } else { filters.push({ [mongoField]: value }); } }); const items = await Item.find({ $and: filters }); return items; } catch (err) { throw err; } }
内容的提问来源于stack exchange,提问作者Pjotr Mega
相关产品推荐
相关产品推荐

