仅在变量不为null时如何应用Hasura`where`过滤器?

时间:2019-04-23 11:02:03

标签: hasura

我有这样的查询:

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过滤器的任何部分
  • _is_null_or一样使用Hasura boolExps,但似乎它们不能直接测试变量,它们只能将变量与列内容进行比较

3 个答案:

答案 0 :(得分:3)

您可以使用 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: {} }

答案 1 :(得分:2)

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

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

1.3.4 版之前

This answer 描述了它。

1.3.4 版之后

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

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

如果您想与某个值进行比较并在值为 true 时计算为 null,您需要在客户端站点上处理这种情况并将整个布尔表达式传递给 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。

答案 2 :(得分:0)

如果使用_eq boolExp,则默认情况下,如果变量为null,则全部匹配似乎是默认行为。我没有看到此消息,因为此查询使用的是use Symfony\Component\Serializer\NameConverter\NameConverterInterface; class MappingNameConverter implements NameConverterInterface { public function __construct(array $mapping) { $this->mapping = $mapping; } public function denormalize($propertyName) { return $this->mapping[$propertyName]; } }

如果$ setId作为use Symfony\Component\Serializer\Encoder\CsvEncoder; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; $mapping = ['full name' => 'name', 'aged' => 'age', ...]; $nameConverter = new MappingNameConverter($mapping); $normalizer = new ObjectNormalizer(null, $nameConverter); $serializer = new Serializer([$normalizer], [new CsvEncoder()]); 传递,则更改为所有项:

_in

这是因为Hasura遵循SQL,使null不具有任何可比性(只有query getUsers ($setId: Int) { user(where: { user_sets: { set_id: { _eq: $setId } } }) { id name status user_sets { set { name } } # more fields... } } 可以匹配在可为空的列中设置为null的值)。

因此,null在逻辑上无法匹配任何内容,因此已对其进行了优化。这个:

_is_null

...成为这个:

{ _eq: null }

...并且由于(where: { user_sets: { set_id: { _eq: $setId } } }) trueExp(被视为true),因此它可以有效地进行优化(where: { user_sets: { set_id: {} } }