【问题标题】:How can I format a Sequelize filter as valid JSON如何将 Sequelize 过滤器格式化为有效的 JSON
【发布时间】:2018-07-06 00:39:05
【问题描述】:

我正在设置一个 API。服务器从客户端接收一个 JSON 格式的过滤器,供 sequelize 在查询 MySQL 数据库时使用。

我一直在用 postman 测试。

下面的json,可以发送到服务器,但是sequelize不喜欢"[Op.or]",因为应该是[Op.or]不带引号。

但是,如果我不添加引号,那么它不是有效的 JSON,我无法发布数据。

//Sequelize does not like this because of the quotes around "[Op.or]"
{
    "filters": {"week": 201740, "project": 8, "itemgroup": {"[Op.or]": ["group1", "group2"]}}
}

//This is can not be sent as a JSON body in an API request because there are
//no quotes around [Op.or]
{
    "filters": {"week": 201740, "project": 8, "itemgroup": {[Op.or]: ["group1", "group2"]}}
}

这是我的脚本文件,其中进行了 sequelize 调用。JSON 过滤器通过函数头中的过滤器变量传入。

module.exports = {
    getAOLDataCount:  function (res, filters) {
        let result = '';
        wd = new WeeklyData(sequelize, Sequelize.DataTypes);
        wd.count({where: filters}).then(function (aolCount) {
            res.send('the value ' + aolCount);
        });
        return result;
    }
};

【问题讨论】:

    标签: json node.js api sequelize.js


    【解决方案1】:

    这是运行 mcranston18 的答案的实现:

    const Op = this.Sequelize.Op;
    this.operatorsMap = { // Add additional operators as needed.
        $ne: Op.ne,
    };
    replaceOperators(oldObject) {
        let newObject = {};
        for (let key in oldObject) {
            let value = oldObject[key];
    
            if (typeof value === 'object') {
                newObject[key] = this.replaceOperators(value); // Recurse
    
            } else if (this.operatorsMap[key]) {
                let op = this.operatorsMap[key];
                newObject[op] = value;
    
            } else {
                newObject[key] = value;
            }
        }
        return newObject;
    }
    

    使用此代码,您可以执行以下操作:

    let whereFilter = {"emailAddress":"xxx@xxx.org","id":{"$ne":7}};
    let objectFilter = JSON.parse(whereFilter);
    let translatedObjectFilter = this.replaceOperators(objectFilter);
    let options = {};
    options.where = translatedObjectFilter;
    await this.table.findAll(options).then(....
    

    通过将字符串运算符转换为适用于 Sequelize 调用的能力,苦苦挣扎的开发人员可以在客户端单页应用程序上完成更多工作,因为无需为每个不同的客户端查询编写带有文字对象的特定服务器端查询。服务器端框架可以是通用的,而不是特定于应用程序的。

    例如,我正在构建的 SPA 有一个只有 5 个 js 文件的服务器框架。客户端有 28 个 js 文件并且还在增长。这使用 Sequelize 4.37.10。

    【讨论】:

      【解决方案2】:

      最后我从 sequelize slack group 中发现,旧的 operator 方法仍在代码库中。我不知道它会停留多久,但由于它是通过json发送的唯一方式,它可能会停留。

      所以它的工作方式是,你可以使用 $or,而不是使用 [Op.or]。

      例子:

      "filters": {"week": 201740, "project": 8, "itemgroup": {"$or": ["group1", "group2"]}}
      

      【讨论】:

      【解决方案3】:

      您的客户端(可能)没有安装 Sequelize,并且无法通过 JSON 传递 Sequelize 运算符,因此您尝试做的事情并不完全可能。您可能会让客户端发送字符串(例如orand,然后您必须将这些字符串映射到 Sequelize 运算符)[1]。

      "filters": {"week": 201740, "project": 8, "itemgroup": {"or": ["group1", "group2"]}}
      

      然后在您的服务器代码中,您需要维护一个字符串映射到 Sequelize 运算符:

      const operatorsMap = {
        or: [Op.or],
        and: [Op.and],
        etc
      }
      

      然后,对于每个请求,您将遍历所有键并用 Sequelize 运算符替换字符串。

      function isObject(o) {
        return o instanceof Object && o.constructor === Object;
      }
      
      function replacer(obj) {
        var newObj = {};
        for (key in obj) {
          var value = obj[key];
      
          if (isObject(value)) {
            newObj[key] = replacer(value);
          } else if (operatorsMap[key]) {
            var op = operatorsMap[key];
            newObj[op] = value;
          } else {
            newObj[key] = value
          }
        }
      
        return newObj;
      }
      
      module.exports = {
          getAOLDataCount:  function (res, filters) {
              let result = '';
              wd = new WeeklyData(sequelize, Sequelize.DataTypes);
              wd.count({where: replacer(filters)}).then(function (aolCount) {
                  res.send('the value ' + aolCount);
              });
              return result;
          }
      };
      

      仅供参考,上面的代码尚未经过测试。

      [1] 在不了解您的项目细节的情况下,我建议您重新考虑这种方法。客户端真的不应该发送直接馈送到 ORM 的 JSON 对象。糟糕的 SQL 注入怎么办?如果您升级 Sequelize 并且旧的过滤器被弃用了怎么办?相反,考虑允许通过查询参数进行过滤,并让您的 API 基于此创建过滤器对象。

      【讨论】:

      • 感谢您的建议。这是在封闭网络上使用的内部应用程序 API,因此 SQL 注入的可能性很小。这种方法的主要驱动力是,当前用 PHP 编写的报告应用程序已经失控,不同的部门想要以不同的方式过滤数据,并且试图跟上不断增长的过滤器列表很累。使用这种方法,客户端可以将其过滤器要求直接推送到 API。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2016-07-27
      • 2015-06-16
      • 2018-02-14
      • 1970-01-01
      • 2019-10-10
      相关资源
      最近更新 更多