Sails.js 如何从筛选条件中排除未定义为模型属性的查询参数
我正在使用带有Blueprint API的sails来进行RESTful处理,我遇到了一个简单GET请求的问题。以下面的模型为例。我们称之为Sails.js 如何从筛选条件中排除未定义为模型属性的查询参数,sails.js,waterline,Sails.js,Waterline,我正在使用带有Blueprint API的sails来进行RESTful处理,我遇到了一个简单GET请求的问题。以下面的模型为例。我们称之为项目: module.exports = { attributes: { id: { type: 'string', unique: true }, name: { type: 'string' },
项目
:
module.exports = {
attributes: {
id: {
type: 'string',
unique: true
},
name: {
type: 'string'
},
displayName: {
type: 'string'
},
...
};
由于我定义了一个ProjectController.js
,Blueprint在GET/project
为我设置了一条路径。如果我向这个URL发出请求,我会得到这个模型的所有未过滤结果,这是正确的。还可以使用其他参数,如limit
,sort
等,例如GET/project?limit=5
,我仍然可以得到所有结果(假设我的结果不超过5个)
问题在于我提供的查询参数不是为API保留的,例如limit
。现在,它使用这个参数作为筛选条件(GET/project?foo
),我没有得到任何结果
我的模型设置为sails.config.models.schema=true
,因此只填充属性中定义的字段,因为我不希望存储垃圾信息。考虑到我是如何指定模型遵循模式的,我希望它也能忽略未定义为属性的筛选条件。本质上,GET/project?foo
应该返回所有结果,因为foo
不是有效的属性
这样做的主要原因是每个请求都会发送一个cache-buster-param,Sails将其解释为一个filter-param,从而扭曲了我的结果
想法?对于MU的后续评论,这里的想法是通用的,而不是特定于模型或控制器。我研究了使用策略的想法,但是接下来我需要定义在每个控制器上使用的策略,这仍然不允许根据具体情况对参数进行更具体的过滤
这里的最终目标是不必在我的控制器中定义任何方法,因为Blueprints会隐式地处理它们(例如,GET project/
会自动使用Blueprintsfind()
方法。不幸的是,我不必定义自己的ProjectController.find(),就无法完全摆脱这种情况
方法,但它似乎非常合理,因为我仍然可以在一行中调用Blueprints中间件
下面是一个示例实用程序模块,用于从请求的不同范围(query
、body
和params
)中剥离参数。希望注释能说明问题:
requestUtils.js
var _ = require('lodash');
module.exports = {
sanitizeRequestParams: function (req, scope, opts) {
var scopes = ['query', 'body', 'params'],
// global params to strip, keep and convert. Additional configurations can be supplied
// in the `opts` argument
stripParams = ['_dc'],
keepParams = [],
convertParams = {
/**
* Convert the `page` param into a calculated `skip` param for ORM
*
* The client-side framework will include the following for model
* requests:
* ?_dc=XXX&limit=XX&page=XX&start=XX
*
* The only one ORM will not use for filter criteria is `limit`. So
* instead of using `page`, we will calculate the number of records
* to skip from the `page` and `limit` params and set that to the
* request instead.
*
* @param param The request param to be converted
* @param val The value of th =e request param
* @param req The Request object
* @returns {{skip: *}}
*/
'page': function (param, val, req) {
var limit = _.toInteger(req.query.limit);
if (!_.isInteger(limit)) {
limit = sails.config.blueprints.defaultLimit;
}
return {'skip': _.max([(_.toInteger(val) * limit) - limit, 0])};
}
};
// default to all if invalid scope specified
if (scopes.indexOf(scope) < 0) {
scope = 'all';
}
opts = opts || {};
// merge in user-provided configs with the defaults
stripParams = _.concat(stripParams, opts.strip || []);
keepParams = _.concat(keepParams, opts.keep || []);
convertParams = _.merge(convertParams, opts.convert || []);
// iterate over each of the scopes to process the params
_.forEach(scopes, function (currScope) {
if (scope === currScope || scope === 'all') {
// strip the defined params from the request, optionally
// keeping the ones marked as such
_.forEach(stripParams, function (param) {
if (keepParams.indexOf(param) < 0) {
// eg: deletes `request.query._dc`
delete req[currScope][param];
}
});
// iterate the params to be converted to a new param
_.forEach(convertParams, function (fn, param) {
var newParam;
// ensure the orig param exists before writing a new one
if (req[currScope][param]) {
newParam = fn(param, req[currScope][param], req);
// eg: deletes `request.query.page`
// adds `request.query.skip` with a calculated value
delete req[currScope][param];
_.merge(req[currScope], newParam);
}
});
}
});
}
};
module.exports = {
find: function (req, res) {
// before: ?_dc=XXXXX&page=XX&limit=XX&start=XX
// after: ?limit=XX&skip=XX
util.sanitizeRequestParams(req, 'query', {strip: ['start']});
// let Blueprints handle the `find` method like we never existed
return sails.hooks.blueprints.middleware.find(req, res);
}
};
可能有一种更干净的方法来处理这个问题,比如生命周期回调或钩子。到目前为止,我还没有使用SAIL或Node,所以对我来说都是绿色的。任何反馈都很感谢。您需要通用的还是可以指定模型