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

如何在Mongoose的$and查询语句中动态嵌套$or操作符

现有代码的核心问题

  1. 字段映射错误:GraphQL入参的过滤字段是titles,但MongoDB集合中对应的存储字段是title,直接用入参的key作为查询字段无法匹配到数据。
  2. 对象引用重复问题:你在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:24:03