【问题标题】:Node-Postgres SELECT WHERE IN dynamic query optimizationNode-Postgres SELECT WHERE IN 动态查询优化
【发布时间】:2015-10-12 12:21:42
【问题描述】:

我们正在使用 node-postgres 包开发带有 Postgres 数据库的 Node/Express Web 应用程序。我们按照this question 中的说明进行操作,并以这种方式编写查询:

exports.getByFileNameAndColName = function query(data, cb) {

  const values = data.columns.map(function map(item, index) {
    return '$' + (index + 2);
  });

  const params = [];
  params.push(data.fileName);
  data.columns.forEach(function iterate(element) {
    params.push(element);
  });

  db.query('SELECT * FROM columns ' +
    'INNER JOIN files ON columns.files_id = files.fid ' +
    'WHERE files.file_name = $1 AND columns.col_name IN (' + values.join(', ') + ')',
    params, cb
  );

};

data 是一个包含字符串fileName 和列名数组columns 的对象。 我们希望此查询从动态列数的“列”和“文件”表中提取信息。 db.query(query, args, cb) 为参数,其中query 是SQL 查询,args 是要传递给查询的参数数组,cb 是与数据库结果一起执行的回调函数。

所以以这种方式编写的代码会返回正确的数据,但是(我们认为)它很难看。我们尝试了不同的方式将参数传递到查询中,但这是唯一成功返回数据的格式。

有没有一种更简洁/更简单的方式来传递我们的参数? (例如,以节点 postgres 将接受的方式传递参数的任何方式,而无需从我的数组 + 非数组元素创建额外的数组。)

问这个是因为:

  1. 也许有更好的方法来使用 node-postgres 包/我们使用不正确,并且
  2. 如果这是解决此类问题的正确方法,则此代码补充了上述问题的答案。

【问题讨论】:

    标签: node.js postgresql node-postgres


    【解决方案1】:

    您好,我尝试翻译“但是(我们认为)它很丑”,我相信我的回答回答了您的问题。 在您引用的同一个问题中,您会发现this response

    用户使用特殊情况variable formatting接受pg-promise

    在您的情况下,使用shared connection 可能看起来像这样,但在您的示例中,我实际上建议使用普通的db.query 我只是使用共享连接向您展示我如何扩展“丑陋”:

    exports.getByFileNameAndColName = function query(data,cb) {
      var sco; 
      const params = [];
      params.push(data.fileName);
      data.columns.forEach(function iterate(element) {
        params.push(element);
      });
      db.connect()
      .then(function(obj){
        sco=obj;
        return sco.query('SELECT * FROM columns ' +
          'INNER JOIN files ON columns.files_id = files.fid ' +
          'WHERE files.file_name = $1 AND columns.col_name IN ($2^)',
        pgp.as.csv(params)));
      },function(reason){
        console.log(reason);
      })
      .done(function(){
        if(sco){
            sco.done();
            cb();
        }
      });
    
    };
    

    现在我不确定你所说的丑陋是什么意思,但在我的用例中,返回格式是这样的:

    {
      column:[
             {
              id: data,
              data: data,
              col_name: data,
              files_id: data,
              fid: data,
              files_name: data
             },...
       ]
    }
    

    就我而言,我真的很想要这个:

    {
          column:[
                  {
                  id: data,
                  data: data,
                  col_name: data,
                  files_id: data,
                  },...
          ],
          file:[
                {
                 fid: data,
                 files_name: data
                },...
          ]
    
        }
    

    因此,为了做到这一点,我采用了相同的共享连接并添加了一个额外的变量来管理结果。现在这可能无法回答您的问题,或者我可能只是在做一些事情,但我建议您查看pg-promises,这可能有助于提前查询和格式化。

    【讨论】:

    • 允许IN ($2^) 的变量格式很有趣。它确实对查询进行了一些清理,但在 pgp.as.csv 实际所做的事情周围增加了一些模糊性。在这种情况下,我认为我的原始代码的意图更清晰。实际上,我们对数据的输出方式也很满意——它被传递给我们的cb 回调函数,并在其他地方毫无问题地处理。
    • @eugene1832, pgp.as.csv 接受一个值数组并将其转换为格式正确的以逗号分隔的值列表,这些值可以传递给函数或WHERE IN(...),就像在这种情况下一样。跨度>
    • @artsmc,在您提供的示例中,使用共享连接绝对没有意义,它只会使示例变得不必要地复杂化。普通的db.query 可以很好地完成这项工作。
    • @vitaly-t 我还提到常规 db.query 可以正常工作。我个人使用共享连接来扩展一些我没有提供示例的功能
    【解决方案2】:

    我的问题是询问是否有一种方法可以使用 node-postgres 库,以便在查询之前清理我们的 params 创建代码。但是,从几个已删除的答案以及剩余的答案来看,我们似乎很生气,而那几行额外的行并不是什么大不了的事,这是编写此代码的最佳方式。所以,我将这个问题标记为“已回答”,尽管现在看来这不是最重要的问题,也许我们一开始就不应该问这个问题。

    【讨论】:

    • 也许some basic examples of using parameters within pg-promise 会为您澄清此事。如果没有,您可以随时在pg-promise home page 上提问。
    • 让我澄清一下:我的意思只是使用 pg-promise 进行变量格式化确实去掉了之前的 3 行代码,但我已经将三行清晰编写的代码换成了整个库的价值仅针对该功能的内容。这就是我说原始代码的意图比提供的使用 pg-promise 的示例更清晰的意思。遵循YAGNI 之类的原则,在这种情况下,我认为使用 pg-promise 库并不是更好的解决方案。
    • 也许,但是您会获得更高级别的一致抽象,这将使您在其他任何地方都受益;)此外,WHERE IN 只是标准参数格式必须调整的一种特殊情况,所以它一般不会影响您代码的cleanness ;)
    猜你喜欢
    • 1970-01-01
    • 2011-12-15
    • 2011-11-24
    • 2015-09-13
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    相关资源
    最近更新 更多