Sails.js 如何从筛选条件中排除未定义为模型属性的查询参数

Sails.js 如何从筛选条件中排除未定义为模型属性的查询参数,sails.js,waterline,Sails.js,Waterline,我正在使用带有Blueprint API的sails来进行RESTful处理,我遇到了一个简单GET请求的问题。以下面的模型为例。我们称之为项目: module.exports = { attributes: { id: { type: 'string', unique: true }, name: { type: 'string' },

我正在使用带有Blueprint API的sails来进行RESTful处理,我遇到了一个简单GET请求的问题。以下面的模型为例。我们称之为
项目

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/
会自动使用Blueprints
find()
方法。不幸的是,我不必定义自己的
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,所以对我来说都是绿色的。任何反馈都很感谢。

您需要通用的还是可以指定模型