简体   繁体   English

在NodeJS中动态构建MongoDB查询

[英]Dynamically building MongoDB queries in NodeJS

I receive a POST argument that looks like this: 我收到一个看起来像这样的POST参数:

sort:
    [ 
        { field: 'name', dir: 'asc', compare: '' },
        { field: 'org', dir: 'asc', compare: '' }
    ] 
}

and I need to create a MongoDB query based on that, so it should look like: 我需要根据它创建一个MongoDB查询,所以看起来应该是这样的:

db.collection("my_collection").find( ... ).sort({'name': 'asc', 'org': 'asc'}).toArray(...);

Anyways, keep in mind that more fields could be passed. 无论如何,请记住可以传递更多字段。 Also, it could happen that none of those fields is passed, meaning that the query won't have .sort() . 此外,可能会发生这些字段都没有传递,这意味着查询不会有.sort()

My question: How can I create dynamically a query with Node's MongoDB driver? 我的问题:如何使用Node的MongoDB驱动程序动态创建查询? Is there a query builder or something similar? 是否有查询构建器或类似的东西?

I've found that most cases are unique regarding passed data, so building query objects varies from project to project. 我发现大多数情况对于传递的数据都是唯一的,因此构建查询对象因项目而异。
So first ideas was to create middleware for express (in my case), that would parse query arguments into objects that are valid for query. 所以最初的想法是为express(在我的例子中)创建中间件,它将查询参数解析为对查询有效的对象。

mongo-native can use as chained options to cursor , as well as in object: mongo-native可以用作游标的链接选项,也可以用作对象:

Chained: 链接:

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

Non-chained: 非链接:

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

As you can see Non-Chained can accept everything as object, while chained returns cursor after every method and can be reused. 正如您所看到的,Non-Chained可以接受所有内容作为对象,而chained会在每个方法之后返回游标,并且可以重复使用。 So generally you have two options: 所以通常你有两个选择:

For Chained: 对于链式:

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

For Non-Chained: 对于非链式:

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

It is important to remember that any data from query have to be validated and parsed properly. 重要的是要记住,必须正确验证和解析来自查询的任何数据。 As well if you are developing API (for example), and will decide to change the way sorting arguments are passed or will want to add new way, then making middleware (in express.js) for parsing this data - is the way to go. 如果你正在开发API(例如),并且决定改变传递排序参数的方式或者想要添加新方法,那么制作中间件(在express.js中)来解析这些数据 - 是要走的路。

Example for pagination: 分页示例:

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();
  }
}

Usage: 用法:

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);
    }
  });
});

And url examples: 和网址示例:

http://example.com/items  
http://example.com/items?skip=64  
http://example.com/items?skip=256&limit=32  

So it is the way to develop well flexible framework, which does not creates any rules of how things have to be coded as well as solving your challenge. 因此,它是开发灵活的框架的方法,它不会创建任何事物必须编码的规则以及解决您的挑战。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM