如何建立动态MongoDB查询

时间:2019-06-17 06:31:02

标签: node.js mongodb mongoose mongodb-query

我有2个MongoDB集合。关键字和PersonalInfo。我从客户端收到这样的数组:

[
 {fieldName : 'Keyword',operator: '===',value: 'soccer'},
 {fieldName : 'Keyword',operator: 'endsWith',value: 'cer'},
 {fieldName : 'Name',operator: 'startsWith',value: 'mik'}
]

我正在使用NodeJ,需要动态构建MongoDB查询。 我已经尝试过了。

 let q = {};
  q["$and"] = [];

  let data = req.body;
  for (let i = 0; i < data.length; i++) {
    // I tried without consideration of "operator" first but couldn't succeed. 

    let val = new RegExp(data[i].value);
    if (data[i].fieldName === "Keyword") {
      q["$and"].push({ Keyword: { $regex: val, $options: "-i" } });
    } else if (data[i].fieldName === "Name") {
      q["$and"].push({ Name: { $regex: val, $options: "-i" } }); //Since this field is from another collection, so instead of Name i want to push it as "$$name" so i could be able to use it in aggregates. 


    } 
  }

我原本希望看到这样的输出。

{$and: 
[
 {Keyword: {$regex: 'search val', $options: "-i"}},
 {Name: {$regex: 'search val', $options: "-i"}},
]
}

但是我得到的是:

{$and: 
 [
 {Keyword: [Object]},
 {Name: [Object]},
]
}

我如何构建以上查询并以类似的方式实现该查询?

await Keyword.aggregate([
 {
  $lookup: {
    from: "PersonalInfo",
    let: { name: "$Name" },
    pipeline: [{ $match: { $expr: q } }],
    as: "searchRecords"
  }
}
 ])

这是我的完整代码。

let q = {};
  let results;
  let data = req.body;
  let and_conds = [];
  for (let i = 0; i < data.length; i++) {
    let val = new RegExp(data[i].value);
    let field_name = data[i].fieldName;
    and_conds.push({ [field_name]: { $regex: val, $options: "-i" } });
  }
  q["$and"] = and_conds;

let records = await KeyInfo.aggregate([
   {
      $lookup: {
        from: "PersonalInfo",
        let: { name: "$name" },
        pipeline: [{ $match: { $expr: q } }],
        as: "searchRecords"
      }
    }
   ]);

感谢您的时间,感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您做得正确,我不确定您是如何获得“输出”的(假设您打印了它),但是它只是向您显示对象内部的内容,这是预期的另一个对象。

完整的代码如下所示:(仅出于可读性考虑将其清除了一点)

  let q = {};

  let data = req.body;
  let and_conds = [];
  for (let i = 0; i < data.length; i++) {
    let val = new RegExp(data[i].value);
    let field_name = data[i].fieldName;
    and_conds.push({[field_name]: { $regex: val, $options: "-i" }})
  } 
  q["$and"] = and_conds;
  • 我不确定$$name注释的含义,因为您仅在匹配阶段查找后使用这些条件,但是如果您要做的只是从{更改field_name值{1}}至"Name"

编辑:

使用它代替上面的语法:

"$$name"

您也没有将您的 let val = new RegExp(data[i].value, "i"); and_conds.push({[field_name]: val)` 更改为fieldName,所以您也应该这样做。