I have a table 'Students' in my db(postgress with Hasura) with relation many-to-many with 'Subjects':
type Student = {
id: uuid
name: String
subjects: [subject]
}
type Subject = {
id: uuid
name: String
}
I have a Static QUERY1:
query FilteredStudents($subjects: [String!]) {
students(where: { subjects: { name: { _in: $subjects } } }) {
id
name
}
}
e.g.:
$subjects = ['Math', 'English', 'Physics']
It will find all the students that attend to ANY of those classes. e.g.:
const student1 = {
id: 1,
name: 'Mike',
subjects: ['Physics', 'Chemistry'] // subjects mapped to names for simplicity
}
My problem is that I want another query which will find all the students that attend to EACH of those classes.
So it shouldn't fetch student1, but should fetch students like this:
const student2 = {
id: 2,
name: 'Walt',
subjects: ['Math', 'English', 'Physics', 'Some', 'other', 'subjects'] // subjects mapped to names for simplicity
}
My only idea was to create dynamic queries like this:
Dynamic QUERY2 (a new query is generated (on runtime) every time the $subject array changes):
query FilteredStudents {
students(where: { _and: [
subjects: { name: { _eq: "Math" } }
subjects: { name: { _eq: "English" } }
subjects: { name: { _eq: "Physics" } }
]}) {
id
name
}
}
But I would really want to avoid that and find some static solution. Is there a way to achieve this using filters offered by Hasura? (https://hasura.io/docs/1.0/graphql/manual/queries/query-filters.html#)
I can name your QUERY2 as static already and QUERY1 as dynamic - 1st is parametrized, 2nd is hardcoded.
You can construct and pass as variable entire where
object for both.
You can read this and use _not
with _nin
to do the same (as '_and' usage). It stil will be a dynamic condition because where
is an input type ... and almost the same condition object creation complexity.
const subset = ['Math', 'English'];
const condition = { _and: [] };
subset.map( el => {
condition._and.push( {
subjects: { name: { _eq: el } }
});
});
callSomeLazyQuery( { variables: {
where: condition
} );
the same should be valid
const condition = {
_not: {
_and: []
}
};
subset.map( el => {
condition._not._and.push( {
subjects: { name: { _nil: el } }
});
});