【问题标题】:How to do SQL query filtering when certain params are not passed in?某些参数未传入时如何进行SQL查询过滤?
【发布时间】:2018-02-17 04:12:51
【问题描述】:

我已经构建了一个 REST 端点来列出项目,/api/items,它可以通过查询参数传递一些选项来过滤结果。

例如,GET /api/items?minPrice=30&maxPrice=100&minRating=4&onSale=true

如何将其转换为我的 SQL 查询?

如果我收到一个只有maxPrice=50 的请求,那么其他参数呢?让我们假设以下是我的查询 -

select * from items 
where minPrice=(???) and maxPrice=50 and minRating=(???) and onSale=(???)

如果没有任何请求,我如何“忽略”过滤器,只过滤maxPrice=50?有没有一种编程方式来做到这一点?

在我的例子中,我使用的是 postgres,所以我使用 &1&2 等参数化了查询,每个查询都有值。

【问题讨论】:

  • 我来自 C# 世界,在那里您通常使用允许您向 SQL 语句添加可选参数的数据层。它可能没有直接帮助,但可能会引发您思考如何在您的世界中解决这个问题,而且它消除了 SQL 注入的风险。
  • 你用的是 express js 吗?
  • 我正在使用 Go + sqlx,移植一个使用 knex 用 node+express 编写一半的应用程序
  • 你试过什么?你遇到了什么问题?
  • 同样的问题解决了:stackoverflow.com/questions/48344888/…

标签: sql node.js postgresql go sqlx


【解决方案1】:

为此,您需要为任何类型的条件编写自定义查询。

通常 ORM 工具做得很好:

在 Java(Spring 和 JPA)的情况下,您可以使用条件 api 和一些帮助程序,其中之一是 Spring Data 的规范构建器模式:

Specifications fullSpec = null;
if (param1 != null) {
    fullSpec = Specifications.where(<... criteria condition for param1 ...>);
}

if (param2 != null) { 
    if (fullSpec != null) {
        specs = fullSpec.and(<define condition using criteria api>);
    } else {
        fullSpec = Specifications.where(<same condition for param2>);
    }
}

当你在 NodeJS 上时(从标签看来是真的)你可以使用Sequelize。直接来自它的教程:

var filterObject = {
    minValue: <its value received from request>, 
    maxValue: <its value received from request>, 
    minRating: <its value received from request>, 
    maxRating: <its value received from request>
  };

// filterout null valued properties out of filter
filterObject = _.compactObject(filterObject);

Items.findAll({
  where: filterObject
});

这就是您以安全的方式获得结果所需要的一切。

此示例使用下划线混合从对象中过滤掉空值,如 This response 所示

您也可以随时按照以下方式编写查询:

var query = 'select * from items where maxPrice=:maxPrice'
if (minPrice) {
    query = query + ' and minPrice=:minPrice'
}
//...
// fill-in all other conditions.
//...
// and then simply query with named parameters.

【讨论】:

    【解决方案2】:

    如果在 REST 调用中未提供这些值,您应该提供有意义的默认值。例如

    minValue = 0 
    maxValue = <veryHighValue>
    minRating = 0
    onSale in (true, false)
    

    或者您可以从这些默认值开始,然后使用 REST 调用提供的值覆盖。

    【讨论】:

      猜你喜欢
      • 2021-03-07
      • 2019-03-04
      • 2022-07-07
      • 2020-03-08
      • 1970-01-01
      • 2012-08-05
      相关资源
      最近更新 更多