Как запросить только эти объекты, содержащие каждый элемент из массива, заданного как переменная, с помощью Hasura?

У меня есть таблица «Студенты» в моей базе данных (postgress with Hasura) с отношением «многие ко многим» с «Subjects»:

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

type Subject = {
    id: uuid
    name: String
}

У меня есть Статический QUERY1:

query FilteredStudents($subjects: [String!]) {
    students(where: { subjects: { name: { _in: $subjects } } }) {
        id
        name
    }
}

e.g.:

$subjects = ['Math', 'English', 'Physics']

Он найдет всех учащихся, посещающих ЛЮБОЙ из этих классов. например.:

const student1 = {
   id: 1,
   name: 'Mike',
   subjects: ['Physics', 'Chemistry']  // subjects mapped to names for simplicity
}

Моя проблема в том, что мне нужен другой запрос, который найдет всех учащихся, посещающих КАЖДЫЙ из этих классов.

Таким образом, он не должен получать student1, а должен получать таких студентов:

const student2 = {
   id: 2,
   name: 'Walt',
   subjects: ['Math', 'English', 'Physics', 'Some', 'other', 'subjects']  // subjects mapped to names for simplicity
}

Моя единственная идея заключалась в создании таких динамических запросов:
Dynamic QUERY2 (новый запрос создается (во время выполнения) каждый раз, когда изменяется массив $ subject):

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

Но мне бы очень хотелось этого избежать и найти какое-то статичное решение. Есть ли способ добиться этого с помощью фильтров, предлагаемых Hasura? (https://hasura.io/docs/1.0/graphql/manual/queries/query-filters.html#)


person conrisc    schedule 04.05.2020    source источник
comment
Ух, я не могу понять этого. Два варианта, о которых я могу думать, не очень хороши. 1. Получите всех пользователей, как вы, в Query 1, а затем отфильтруйте их на клиенте 2. Добавьте все отношения в столбец hasSubjects JSON и затем отфильтруйте следующим образом hasura.io/docs/1.0/graphql/manual/queries/   -  person moto    schedule 06.05.2020


Ответы (1)


Я могу назвать ваш QUERY2 уже статическим, а QUERY1 - динамическим - 1-й параметризован, 2-й жестко запрограммирован.

Вы можете создать и передать как переменную весь объект where для обоих.

Вы можете прочитать this и используйте _not с _nin, чтобы сделать то же самое (как при использовании '_and'). Это по-прежнему будет динамическим условием, потому что where - это тип ввода ... и почти такая же сложность создания объекта условия.

Обновить

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

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

callSomeLazyQuery( { variables: {
  where: condition 
} );

то же самое должно быть действительным

const condition = {
  _not: { 
    _and: [] 
  }
};
subset.map( el => {
  condition._not._and.push( {
    subjects: { name: { _nil: el } } 
  });
});
person xadm    schedule 05.05.2020
comment
Я назвал QUERY1 статическим, потому что он жестко запрограммирован - я могу управлять только переменными, переданными в этот запрос. QUERY2 - это только пример запроса, сгенерированного в runtime, поэтому мне нужно генерировать новый запрос каждый раз, когда изменяется массив $ subject - поэтому я назвал его динамическим. Что касается решения с _not и _nin - это уже пробовали, но оно соответствует только студентам, у которых точно такие же предметы, которые я ему передаю. Для $subjects=['Math', 'German'] он вернет студентов только с этими предметами, но я хотел бы получить также студентов, например: ["Math", "German", "Chemistry"]. - person conrisc; 06.05.2020
comment
кто жестко запрограммировал? кем? запросы не должны генерироваться - это плохая практика (например, манипулирование строками для привязки SQL-запроса) ... при изменении сервера ожидается только один аргумент для where, и ваше приложение должно создать и передать в качестве переменной этот один параметр - person xadm; 06.05.2020
comment
_not и _nin должны работать, может быть _not _and _nin? - тестируйте пошагово, _nin в одиночку ... если вы уверены, что это сработает, подготовьте доказательство минимальный воспроизводимый пример и подать вопрос? .... в любом случае - можно использовать уже работающие _and _eq - person xadm; 06.05.2020
comment
жестко запрограммированный - мной, сгенерированный функцией (во время выполнения). Да, я считаю, что это плохая практика, поэтому я спрашиваю, есть ли лучшее решение. Я хотел бы использовать простой where, но, похоже, простого решения нет (или я не могу его найти). Я только что показал вам, почему _not и _nin не работают. Гадать, какая комбинация _not _and _nin может сработать, - ужасный подход. вы можете использовать уже работающие _и _eq - это довольно смелое предположение, есть идеи, как может выглядеть такой запрос? потому что я ничего не придумал. - person conrisc; 06.05.2020
comment
см. обновленный ответ ... логические комбинации могут быть разложены и проверены шаг за шагом во время перестройки (вы можете проверить один _nin, два _nin с помощью _и и отрицание одного _nin и т. д.), это не страшно;) - person xadm; 07.05.2020
comment
Спасибо! Это то, что я искал, я не знал, что могу передать целый where (типа BoolExp) в качестве параметра запроса. - person conrisc; 08.05.2020