【问题标题】:How to apply a Hasura `where` filter only if a variable is not null?仅当变量不为空时,如何应用 Hasura `where` 过滤器?
【发布时间】:2019-09-12 13:16:34
【问题描述】:

我有一个这样的查询:

query getUsers ($setId: Int) {
  user(where: { user_sets: { set_id: { _in: [$setId] } } }) {
    id
    name
    status
    user_sets {
      set {
        name
      }
    }
    # more fields...
  }
}

我正在寻找的是一种不应用where 过滤器并在$setId 为空时提供所有条目的方法。我想避免动态编写查询 - 这样做很容易,但我们希望在静态 .graphql 文件中进行查询:

const query = `
query getUsers (${ setId ? '$setId: Int' : ''}) {
  user(${ setId ? 'where: { user_sets: { set_id: { _in: [$setId] } } }' : '' }) {
`

我尝试过的一些事情:

  • @skip@include 一样使用GraphQL directives,但似乎这些仅适用于返回的字段,不适用于where 过滤器的任何部分
  • 使用Hasura boolExps_is_null_or,但似乎这些不能直接测试变量,它们只能将变量与列内容进行比较

【问题讨论】:

    标签: hasura


    【解决方案1】:

    如果使用了_eq boolExp,那么如果变量为空,则匹配所有似乎是默认行为。我没有看到这个,因为这个查询使用了_in

    如果 $setId 作为 null 传递,则更改为所有项目:

    query getUsers ($setId: Int) {
      user(where: { user_sets: { set_id: { _eq: $setId } } }) {
        id
        name
        status
        user_sets {
          set {
            name
          }
        }
        # more fields...
      }
    }
    

    这是因为 Hasura 遵循 SQL,使 null 无法与任何东西进行比较(只有 _is_null 可以匹配可空列中设置为 null 的值)。

    因此,{ _eq: null } 在逻辑上无法匹配任何内容,因此它只是被优化掉了。这个:

    (where: { user_sets: { set_id: { _eq: $setId } } })
    

    ...变成这样:

    (where: { user_sets: { set_id: {} } }
    

    ...因为{}trueExp,被视为真,它优化为有效WHERE 'true'

    【讨论】:

    • 对于gteltein 的空数组等其他选项是否有解决方案?
    • 这在 v2.0 中有所改变。发布说明中的更多内容,行为更改部分:github.com/hasura/graphql-engine/releases/tag/v2.0.0-alpha.1
    • @Friedrich 如果你能写出最新的 v2.0 答案,那就太好了
    • @Friedrich 我想更多的是您将其发布为您自己的答案,我会接受它(我也可能会在我的评论中编辑一条评论,说我的适用于 v1.x 并链接到你作为 v2.x 的答案)。这样你就可以得到它的功劳,你就能更好地保持更新或响应 cmets(我不再与 Hasura 合作,所以我不能这样做)。此外,SO 通常不喜欢这样的 3rd 方编辑的大变化。
    • 好的,我会这样做的。
    【解决方案2】:

    在这种情况下,您可以使用 bool 表达式作为绑定变量

    query getUsers ($condition: user_bool_exp!) {
      user (where: $condition) {
        id
        name
        status
        user_sets {
          set {
            name
          }
        }
        # more fields...
      }
    }
    

    你可以根据你的变量建立条件

    { condition: { user_sets: { set_id: { _in: [$setId] } } } }
    

    { condition: { user_sets: {} }
    

    【讨论】:

      【解决方案3】:

      这种行为在 v1.3.4 之间发生了变化。因此有两个正确答案。

      您可以在hasura repository 中阅读有关此更改的更多信息。

      1.3.4版本之前

      This answer 描述了它。

      1.3.4 之后

      在默认为true 时在比较中使用null 是危险的,因为意外取消设置的变量可能会导致表被删除。维护者删除了这种行为,但通过设置变量 HASURA_GRAPHQL_V1_BOOLEAN_NULL_COLLAPSE 使其可访问。

      {_eq: null} Hasura 比较时会抛出错误,因为假设这是一个错误。

      如果您想与一个值进行比较并在该值为null 时评估为true,您需要在客户端站点上处理这种情况并将整个布尔表达式传递给hasura。

      query getUsers ($userSetsWhere: user_sets_bool_exp) {
        user(where: { user_sets: { $userSetsWhere } }) {
          id
          name
          status
          user_sets {
            set {
              name
            }
          }
          # more fields...
        }
      }
      
      const userSetsWhere = setId ? { set_id: { _eq: $setId } } : {};
      

      只有当值不是 nullundefined 时,才会将非空表达式传递给 hasura。

      【讨论】:

      • 这应该是最佳答案,因为 Hasura 现在是 v2。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-05
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多