仅当变量不为空时,如何应用 Hasura `where` 过滤器?

Posted

技术标签:

【中文标题】仅当变量不为空时,如何应用 Hasura `where` 过滤器?【英文标题】:How to apply a Hasura `where` filter only if a variable is not null? 【发布时间】: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,但似乎这些不能直接测试变量,它们只能将变量与列内容进行比较

【问题讨论】:

【参考方案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。

以上是关于仅当变量不为空时,如何应用 Hasura `where` 过滤器?的主要内容,如果未能解决你的问题,请参考以下文章

仅当搜索栏文本不为空时,如何运行过滤器功能?

SwiftUI:仅当输入不为空时才启用保存按钮

仅当字段不为空时才进行电子邮件验证

仅当表不为空时,T-SQL 才连接表

MSSQL - 仅当所有值都不为空时才插入值

JPA:仅当结果集不为空时才缓存查询