【问题标题】:How to build a conditional query in Mongoose?如何在 Mongoose 中构建条件查询?
【发布时间】:2013-11-10 15:54:16
【问题描述】:

以下代码仅适用于 no 查询字符串或 one 查询字符串。换句话说,只需转到/characters 即可返回所有字符。但是如果你要指定一个查询字符串参数/characters?gender=male,它将只返回男性字符。

如何扩展它以使用 123no 查询字符串? 我真的希望避免为每种情况编写 8 或 9 个不同的 if 语句。我希望 Mongoose 会简单地忽略 nullundefined$where 子句,但事实并非如此(请参阅注释掉的代码)。

  var gender = req.query.gender;
  var race = req.query.race;
  var bloodline = req.query.bloodline;

  var query = Character.find();

  if (gender)
    query = query.where('gender').equals(gender);
  if (race)
    query = query.where('race').equals(race);
  if (bloodline)
    query = query.where('bloodline').equals(bloodline);

  /*
  query
    .where('gender').equals(new RegExp('^' + gender + '$', 'i'))
    .where('race').equals(new RegExp('^' + race + '$', 'i'))
    .where('bloodline').equals(new RegExp('^' + bloodline + '$', 'i'));
  */

  query.exec(function(err, characters) {
    if (err) throw err;
    res.send(characters);
  });

编辑: 好吧,我想我现在可以用 7 个 if 语句来做到这一点。除非有人找到更优雅的解决方案。

编辑 2:

谢谢各位。很难选择一个答案,因为你们俩都帮助我实现了这个简洁的解决方案。这就是现在的全部内容。

var conditions = {};

for (var key in req.query) {
  if (req.query.hasOwnProperty(key)) {
    conditions[key] = new RegExp('^' + req.query[key] + '$', 'i');
  }
}

var query = Character.find(conditions);
query.exec(function(err, characters) {
  if (err) throw err;
  res.send({ characters: characters });
});

【问题讨论】:

  • 没问题,但您应该选择一个答案让未来的用户知道哪个对您更有帮助。如果做不到,请考虑编写自己的答案并检查其是否正确。
  • 你应该删除你的 Edit 2 并写下你自己的答案,这很好顺便说一句
  • 非常好 - 效果很好;除了产生奇怪查询的正则表达式的卫生部分。

标签: javascript node.js mongodb express mongoose


【解决方案1】:

您不需要重复调​​用Query#where,因为您可以将所有条件传递给Mongoose Model#find

var filteredQuery = {},
  acceptableFields = ['gender', 'race', /* etc */ ];

acceptableFields.forEach(function(field) {
  req.query[field] && filteredQuery[field] = req.query[field];
});

var query = Character.find(filteredQuery);

您还需要根据您考虑的允许参数对req.query 进行清理。

【讨论】:

    【解决方案2】:

    我正在为此任务使用对象的破坏。

    const filter = req.query.filter ? { _id: { $in: req.query.filter.split(',') } } : {};
    const category = req.query.category ? { category: req.query.category } : {};
    // more variables that you need and are empty objects if don't exist
    
    const all = await Post.find({ ...filter, ...category }).exec();
    

    【讨论】:

      【解决方案3】:

      嗯,

      我会推荐这样的东西:

      var query = Character.find()
      if(req.params.length < 0) {
        for(var key in req.params) {
          query.where(req.params[key]).equals(key);
        }
      } else {
        // do something without query params
      }
      

      我没有对此进行测试,但它应该可以工作(也许你需要稍微修改一下,但你明白了)。这个解决方案就是不检查参数中的实际内容,所以要确保只有好的东西进来或在 for 循环的某个地方验证它,但需要一些正则表达式或 if 语句。

      希望对你有所帮助。

      【讨论】:

      • 致未来的访问者:已接受答案的示例不起作用。我什至没有使用 req.params,而是使用 req.query。我没有链接.where,而是动态构建一个condition 对象,然后将其传递给Character.find()。请参阅我的编辑#2。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-08
      相关资源
      最近更新 更多