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

时间:2017-01-10 05:51:15

标签: sails.js waterline

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

module.exports = {

    attributes: {
        id: {
            type: 'string',
            unique: true
        },

        name: {
            type: 'string'
        },

        displayName: {
            type: 'string'
        },

        ...
};

由于我已定义ProjectController.js,因此蓝图在GET /project为我设置路线。如果我向此URL发出请求,我会获得此模型的所有未经过滤的结果,这是正确的。还有limitsort等其他参数可以使用,例如GET /project?limit=5,我仍然可以获得所有结果(假设我没有超过limit 5)。

问题在于我提供的查询参数不是为GET /project?foo等API保留的。现在,它使用此参数作为过滤条件(sails.config.models.schema = true),我得不到任何结果。

我的模型设置为attributes,因此只会填充GET /project?foo中定义的字段,因为我不希望存储垃圾信息。看到我如何为模型指定遵循模式,我理想地希望它也忽略未定义为属性的过滤条件。基本上,foo应返回所有结果,因为VB6不是有效属性。

这样做的主要原因是每个请求都有一个缓存破坏者参数,并且Sails将其解释为过滤器参数,从而扭曲了我的结果。

思想?

1 个答案:

答案 0 :(得分:0)

在回应M U的后续评论时,这里的想法是通用的,而不是模型或控制器特有的。我研究了使用策略的想法,但后来我需要定义要在每个控制器上使用的策略,这仍然不允许根据具体情况对params进行更具体的过滤。

这里的最终目标是不必在我的控制器中定义任何方法,因为Blueprints隐式处理它们(例如。GET project/会自动使用Blueprints find()方法。不幸的是我无法完全获得不必定义我自己的ProjectController.find()方法,但它似乎很合理,因为我仍然可以在一行中调用Blueprints中间件。

这是一个示例实用程序模块,用于从请求的不同范围(querybodyparams)中删除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);
                    }
                });
            }
        });
    }
};

<强> ProjectController.js

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

可能有一种更清晰的方法来处理这种问题,例如生命周期回调或钩子。到目前为止我还没有使用Sails和Node,所以它对我来说仍然是绿色的。任何反馈都表示赞赏。