如何使用 Hasura 仅查询包含作为变量给出的数组中每个元素的对象?

con*_*isc 1 apollo reactjs graphql hasura

我的数据库中有一个表“学生”(带有 Hasura 的 postgress),与“主题”具有多对多关系:

type Student = {
    id: uuid
    name: String
    subjects: [subject]
}

type Subject = {
    id: uuid
    name: String
}
Run Code Online (Sandbox Code Playgroud)

我有一个静态 QUERY1

query FilteredStudents($subjects: [String!]) {
    students(where: { subjects: { name: { _in: $subjects } } }) {
        id
        name
    }
}
Run Code Online (Sandbox Code Playgroud)

例如:

$subjects = ['Math', 'English', 'Physics']
Run Code Online (Sandbox Code Playgroud)

它将找到参加任何这些课程的所有学生。例如:

const student1 = {
   id: 1,
   name: 'Mike',
   subjects: ['Physics', 'Chemistry']  // subjects mapped to names for simplicity
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我想要另一个查询,它将找到参加这些课程的所有学生。

所以它不应该获取Student1,但应该像这样获取学生:

const student2 = {
   id: 2,
   name: 'Walt',
   subjects: ['Math', 'English', 'Physics', 'Some', 'other', 'subjects']  // subjects mapped to names for simplicity
}
Run Code Online (Sandbox Code Playgroud)

我唯一的想法是创建这样的动态查询:
Dynamic QUERY2 (每次 $subject 数组更改时都会生成一个新查询(在运行时)):

query FilteredStudents {
    students(where: { _and: [
        subjects: { name: { _eq: "Math" } }
        subjects: { name: { _eq: "English" } } 
        subjects: { name: { _eq: "Physics" } } 
    ]}) {
        id
        name
    }
}
Run Code Online (Sandbox Code Playgroud)

但我真的想避免这种情况并找到一些静态解决方案。有没有办法使用 Hasura 提供的过滤器来实现这一目标?(https://hasura.io/docs/1.0/graphql/manual/queries/query-filters.html#

xad*_*adm 5

我可以将您的 QUERY2 命名为静态,将 QUERY1 命名为动态 - 第一个是参数化的,第二个是硬编码的。

您可以为两者构造整个对象并将其作为变量传递where

您可以阅读本文并使用_notwith_nin执行相同的操作(如“_and”用法)。它仍然是一个动态条件,因为它where是一种输入类型......并且条件对象创建复杂性几乎相同。

更新

const subset = ['Math', 'English'];

const condition = { _and: [] };
subset.map( el => {
  condition._and.push( {
    subjects: { name: { _eq: el } } 
  });
});

callSomeLazyQuery( { variables: {
  where: condition 
} );
Run Code Online (Sandbox Code Playgroud)

同样应该有效

const condition = {
  _not: { 
    _and: [] 
  }
};
subset.map( el => {
  condition._not._and.push( {
    subjects: { name: { _nil: el } } 
  });
});
Run Code Online (Sandbox Code Playgroud)