GraphQL "all" in array query? - graphql

I'm trying to build a GraphQL query within Strapi (probably not relevant) and I'm not sure how to achieve what I want. So far I've got the following, which is close, but name_in isn't quite what I want.
query {
events(where: { audiences: { name_in: ["Year 1", "Biology"] } }) {
name
audiences {
name
}
}
}
What I'm trying to achieve is events where all of the audience names overlap with the provided query which I ultimately wish to parameterise. Here _in is obviously doing an any. So I only want records with ["Year 1"], ["Biology"] or ["Year 1", "Biology"]. Anything else such as ["Year 2", "Biology"] should not be returned as the complete set of audiences doesn't completely overlap.
Is this possible with vanilla GraphQL or do I need to start write custom resolvers?

Related

How to query a map of id with graphql?

I am trying to query an array of ids with graphQl. The query works with a single id as a variable. However it doesn't work when I enter an array of ids.
Here is my gql query with variables:
query GetAuthorContent($id: [ID]!, $idType: AuthorIdType) {
expert(id: $id, idType: $idType) {
excerpt
featuredImage {
node {
description
author {
node {
description
}
}
}
}
slug
}
}
{"id": ["author-1", "author-2", "author-3"], "idType": "SLUG" }
You can look at the definition of the graphql endpoint using a client and see if the Arrays are supported with query.
If it's supported, check the mutation signature and pass accordingly. In this case I think the services does not support querying using an Array.
Hi everyone and thank you for your help.
You guys were right, my DB doesn't allow an array of authors if it is per author singular. However it works with authors plural. This is the way my db works.
Hope it can help someone in the same situation.

How are arguments added to GraphQL, do they need to be defined before?

Hi Everyone I am just trying to learn graphql as I am using Gatsby. I want to know does each field in graphql take an argument or does it need to be defined somehow before. So for example if you visit this link graphql search results
https://graphql.org/swapi-graphql?query=%7B%0A%09allPeople%20%7B%0A%09%20%20people%20%7B%0A%09%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20birthYear%0A%20%20%20%20%20%20eyeColor%0A%09%20%20%7D%0A%09%7D%0A%7D%0A
If i wanted to limit people by eye color how would I do that. In the docs it seems easy as you would just do something like people(eyecolor: 'brown') but that doesn't seem possible. Am I missing something? I basically want to do a SQL style search for all people where eye color is brown.
Thanks.
Arguments need to be defined in the schema and implemented in the resolver. If you're consuming a 3rd party API (like the link you provided), you're limited to their schema. You can tell by looking at their schema (by clicking Docs on the right side of the page) which fields take arguments. For example, person takes id and personID arguments:
people doesn't take any arguments, as seen in the schema:
If you're building your own schema, you can add arguments to any field, and when you implement the resolver for that field you can use the arguments for logic in that resolver.
If you're working with a schema that you don't control, you'll have to add filtering on the frontend:
const {people} = data.allPeople;
const brownEyedPeople = people.filter(({eyeColor}) => eyeColor === 'brown');
When you start developing in Gatsby and actually pull your data into Gatsby, there will be a filter query option that automatically becomes available in the query arguments.
https://www.gatsbyjs.org/docs/graphql-reference/#filter
You can expect to be able to filter your people by eyeColor by using the below query:
{
allPeople(filter: { eyeColor: { eq: "brown" } }) {
edges {
node {
id
name
birthYear
eyeColor
}
}
}
}

GatsbyJS passing user input to GraphQL

I’m looking for examples / tutorials on accepting user input from a form in GatsbyJS and passing that to my GraphQL query.
I can get the user input on submit and also pass variables in when testing graphiql, I just can’t figure out how to combine the two.
My data is stored in Drupal and is a list of recipes.
I’d like the user to be able to type in an ingredient e.g. chicken and then retrieve all of the recipes where chicken is an ingredient.
My query is
query SearchPageQuery($ingredient: String) {
allNodeRecipes(filter: {relationships: {field_ingredients: {elemMatch: {title: {eq: $ingredient}}}}}) {
edges {
node {
id
title
path {
alias
}
relationships {
field_ingredients {
title
}
}
}
}
}
}
If I’m understanding your question correctly, the short answer is you can’t, but another approach might work for you.
Gatsby’s GraphQL queries are run in advance as part of the static build of the site, so the data is part of the client-side JavaScript, but the queries have already been run by that point.
This is the same reason you can’t use JavaScript template literals in a StaticQuery:
// This doesn’t work
let myDynamicSlug = 'home'
return (
<StaticQuery
query={graphql`
query ExampleQuery {
examplePage(slug: { eq: ${myDynamicSlug} }) {
title
}
}
`}
render={data => {
console.log(data)
}}
/>
)
You’ll get an error message explaining “String interpolations are not allowed in graphql fragments.” Further reading: https://github.com/gatsbyjs/gatsby/issues/2293
I had a similar problem recently, and I realised it made a lot of sense why you can’t do this. If you are, ex. generating images using the queries in your GraphQL and things akin to that, you can’t pass in client side variables, because all the “static site” Gatsby operations like handling the images have are already done by that time.
What worked for me was to get the larger portion of data I needed in my query, and find what I needed within. In my previous example, that might mean getting allExamplePages instead of one examplePage, and then finding the myDynamicSlug I needed within it:
// This isn’t exactly how you’d hope to be able to do it,
// but it does work for certain problems
let myDynamicSlug = 'home'
return (
<StaticQuery
query={graphql`
query ExampleQuery {
# You might still be able to limit this query, ex. if you know your item
# is within the last 10 items or you don’t need any items before a certain date,
# but if not you might need to query everything
allExamplePages() {
edges {
node {
title
slug
}
}
}
}
`}
render={data => {
// Find and use the item you want, however is appropriate here
data.edges.forEach(item => {
if (item.node.slug === myDynamicSlug) {
console.log(item)
}
})
}}
/>
)
In your case, that hopefully there is an equivalent, ex. looking something up based on the user input. If you can be more specific about the structure of your data, I’d be happy to try and make my suggestion more specific. Hope that helps!

How to approach a GraphQL query that returns a boolean value?

Need to check whether an email is available or taken during the user sign-up process. The goal is to quickly query, using GraphQL, the API server and have it tell us if the email is available or taken.
What is the general best practice on a simple boolean-ish type of situation using GraphQL?
Below is what I have come up with but I am unsure if this is a good practice or not and want to hear feedback on a better practice on queries like this.
Request:
query {
emailExists(email:"jane#doe.com") {
is
}
}
Response:
{
"data": {
"emailExists": {
"is": true
}
}
}
A "query" is just a field on what happens to be the Query type. A field can return any output type, including scalars -- it doesn't need to return an object. So it's sufficient to have a schema like:
type Query {
emailExists(email: String!): Boolean!
}
The only reason to prefer an object type would be if you anticipated wanting to add additional fields in the future (i.e. something other than your current is field).

Can graphql return aggregate counts?

Graphql is great and I've started using it in my app. I have a page that displays summary information and I need graphql to return aggregate counts? Can this be done?
You would define a new GraphQL type that is an object that contains a list and a number. The number would be defined by a resolver function.
On your GraphQL server you can define the resolver function and as part of that, you would have to write the code that performs whatever calculations and queries are necessary to get the aggregate counts.
This is similar to how you would write an object serializer for a REST API or a custom REST API endpoint that runs whatever database queries are needed to calculate the aggregate counts.
GraphQL's strength is that it gives the frontend more power in determining what data specifically is returned. Some of what you write in GraphQL will be the same as what you would write for a REST API.
There's no automatic aggregate function in GraphQL itself.
You can add a field called summary, and in the resolve function calculate the totals.
You should define a Type of aggregated data in Graphql and a function you want to implement it. For example, if you want to write the following query:
SELECT age, sum(score) from student group by age;
You should define the data type that you want to return:
type StudentScoreByAge{
age: Int
sumOfScore: Float
}
and a Graphql function:
getStudentScoreByAge : [StudentScoreByAge]
async function(){
const res = await client.query("SELECT age, sum(score) as sumOfScore
from Student group by age");
return res.rows;
}
... need graphql to return aggregate counts? Can this be done?
Yes, it can be done.
Does GraphQL does it automatically for you? No, because it does not know / care about where you get your data source.
How? GraphQL does not dictate how you get / mutate the data that the user has queried. It's up to your implementation to get the requested aggregated data. You could get aggregated data directly from your MongoDB and serve it back, or you get all the data you need from your data source and do the aggregation yourself.
If you are using Hasura, in the explorer, you can definitely see an "agregate" table name, thus, your query would look something similar to the following:
query queryTable {
table_name {
field1
field2
}
table_name_aggregate {
aggregate { count }
}
}
In your results, you will see the total row count for the query
"table_name_aggregate": {
"aggregate": {
"count": 9973
}
This depends on whether you build the aggregator into your schema and are able to resolve the field.
Can you share what kind of GraphQL Server you're running? As different languages have different implementations, as well as different services (like Hasura, 8base, and Prisma).
Also, when you say "counts", I'm imagining a count of objects in a relation. Such as:
query {
user(id: "1") {
name
summaries {
count
}
}
}
// returns
{
"data": {
"user": {
"name": "Steve",
"summaries": {
"count": 10
}
}
}
}
8base provides the count aggregate by default on relational queries.

Resources