在NodeJS中动态构建MongoDB查询

ale*_*nst 5 javascript mongodb node.js

我收到一个POST看起来像这样的论点:

sort:
    [ 
        { field: 'name', dir: 'asc', compare: '' },
        { field: 'org', dir: 'asc', compare: '' }
    ] 
}
Run Code Online (Sandbox Code Playgroud)

我需要根据它创建一个MongoDB查询,所以看起来应该是这样的:

db.collection("my_collection").find( ... ).sort({'name': 'asc', 'org': 'asc'}).toArray(...);
Run Code Online (Sandbox Code Playgroud)

无论如何,请记住可以传递更多字段.此外,可能会发生这些字段都没有传递,这意味着查询将不会.sort().

我的问题:如何使用Node的MongoDB驱动程序动态创建查询?是否有查询构建器或类似的东西?

mok*_*oka 7

我发现大多数情况对于传递的数据都是唯一的,因此构建查询对象因项目而异.
所以最初的想法是为express(在我的例子中)创建中间件,它将查询参数解析为对查询有效的对象.

mongo-native可以用作游标的链接选项,也可以用作对象:

链接:

items.find({ type: 'location' }).sort({ title: 1 }).limit(42).toArray(function(err, data) {
  // ...
});
Run Code Online (Sandbox Code Playgroud)

非链接:

items.find({ type: 'location' }, { sort: { title: 1 }, limit: 42 }).toArray(function(err, data) {
  // ...
});
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,Non-Chained可以接受所有内容作为对象,而chained会在每个方法之后返回游标,并且可以重复使用.所以通常你有两个选择:

对于链式:

var cursor = items.find({ type: 'location' });
if (sort) {
  cursor.sort(sort);
}
cursor.toArray(function(err, data) {
  // ...
});
Run Code Online (Sandbox Code Playgroud)

对于非链式:

var options = { };
if (sort) {
  options.sort = sort;
}
items.find({ type: 'location' }, options).toArray(function(err, data) {
  // ...
});
Run Code Online (Sandbox Code Playgroud)

重要的是要记住,必须正确验证和解析来自查询的任何数据.如果你正在开发API(例如),并决定改变传递排序参数的方式或者想要添加新方法,那么制作用于解析这些数据的中间件(在express.js中)就是要走的路. .

分页示例:

function pagination(options) {
  return function(req, res, next) {
    var limit = options.limit ? options.limit : 0;
    var skip = 0;

    if (req.query.limit) {
      var tmp = parseInt(req.query.limit);
      if (tmp != NaN) {
        limit = tmp;
      }
    }
    if (req.query.skip) {
      var tmp = parseInt(req.query.skip);
      if (tmp != NaN && tmp > 0) {
        skip = tmp;
      }
    }

    if (options.max) {
      limit = Math.min(limit, options.max);
    }
    if (options.min) {
      limit = Math.max(limit, options.min);
    }

    req.pagination = {
      limit: limit,
      skip: skip
    };
    next();
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

app.get('/items', pagination({
  limit: 8, // by default will return up to 8 items
  min: 1, // minimum 1
  max: 64 // maximum 64
}), function(req, res, next) {
  var options = {
    limit: req.pagination.limit,
    skip: req.pagination.limit
  };
  items.find({ }, options).toArray(function(err, data) {
    if (!err) {
      res.json(data);
    } else {
      next(err);
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

和网址示例:

http://example.com/items  
http://example.com/items?skip=64  
http://example.com/items?skip=256&limit=32  
Run Code Online (Sandbox Code Playgroud)

因此,它是开发灵活的框架的方法,它不会创建任何事物必须编码的规则以及解决您的挑战.