Graphql- How to fetch result based on the condition of a field? - graphql

I have a query that look like this:
query MyQuery {
products {
edges {
node {
featured
id
image {
altText
mediaItemUrl
slug
}
productId
name
onSale
}
}
}
}
What I want is only fetch the result that featured field is true, if the featured is false, then it never shown in the result.
Something like query like below in mysql:
SELECT id,image,name, featured FROM products WHERE featured = 'false'
But in graphql query above, I can't query the featured = false.
I tried:
query MyQuery {
products {
edges {
node {
featured #include(if: false)
id
... other field I need
}
}
}
}
But what this query do is, if featured field is true, then included the featured field in the result, else don't included the field in the result.This is not what I want.
What I want is,
If featured field of a product is true, then include the products into the result, else, remove the whole product from the result.
How can I achieve this in the MyQuery above?

The #include and #skip directives are used for field selection, not filtering. GraphQL has no built-in way of doing filtering, sorting or pagination. It's up to each individual service to implement these features by exposing the appropriate arguments.
In this case, products could expose an argument named filter or isFeatured to add the ability to filter the results by the featured value. The field's resolver should then use that argument value to determine the correct value to return.
If you're writing client queries and consuming a schema you did not write, check your API's documentation to determine what arguments are available for the products field. If the schema doesn't expose this capability and you don't have a way to change it, then as a client you don't have many options. At best, you can handle the filtering yourself after the result is fetched, but this is troublesome if you also use pagination.

Related

GraphQL dynamic query strategy best practices

What is a good strategy for dynamically building a query schema for objects and fields with Apollo Client and GraphQL?
We have T-Shirt, Pants, and Shoes objects in our schema. Each of these vary on the types of fields readily available.
There are two input fields, a single entity drop down for TShirt, Pants, and Shoes, and a multi-select drop down to select from the fields available from the schema.
The query schema is produced based on the user's input.
const schema = gql
`query {
tshirt {
logo
brand
}
pants {
length
wasteSize
}
shoes {
lacesStyle
color
}
}
}`
query {
tshirt($logoSkipVal: Boolean! = false, $brandSkipVal: Boolean! = false) {
logo #skip(if: $logoSkipVal)
brand #skip(if: $brandSkipVal)
}
}
I have it working with interpolation manipulation. However, you could imagine as the fields grow in abundance so does the amount of skip directives. Is there maybe a way to use #skip or #include to check if a GraphQL variable with a list of strings includes the field name?
Is there any reason you aren't using Fragments to accomplish this? It seems to be the most applicable solution for combining shared logic between queries and mutations.

Query does not return some items from DynamoDB via GraphQL

May I please know what is the reason why are items in DynamoDB not being fetched by GraphQL?
When searching via the DynamoDB console interface, I could easily see and query the item in there but once used in GraphQL, some items are not showing. Mind you, this isn't a connection problem because I could query items its just there's a specific item that is not being returned.
For example, if I query all Posts, it will return all posts in an array but the item is not showing there. However, when I try to query a Post just by targetting it by its ID, it is working well.
Example code that is not working:
listPosts(filter: {groupID: {eq: "25"}}) {
items {
id
content
}
}
but when I do this, it is working well:
getPost(id: "c59ce7e9") {
id
content
}
I had this same issue and can share what i found and worked for me.
The default resolver for the list operation has a limit:20 built in.
{
"version": "2017-02-28",
"operation": "Scan",
"filter": #if($context.args.filter) $util.transform.toDynamoDBFilterExpression($ctx.args.filter) #else null #end,
"limit": $util.defaultIfNull($ctx.args.limit, 20),
"nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.nextToken, null)),
}
I imagine you could change this or you could add a limit filter to your query like this:
listPosts(filter: {groupID: {eq: "25"}}, limit:100) {
items {
id
content
}
}
The limit should be higher than the number of records.
You can see that this would be an issue because it is using the scan operation meaning it inspects each record for a match. this would hurt performance. you could add pagination or you should craft a query for this. you will need to look into pagination, relations and connection.
https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html#advanced-relations-and-pagination

How to filter the products based on product_type, that are retrieved using collectionByHandle in shopify storefront graphQL api?

In our app, we are displaying the list of collections from the shopify store. When user click on any of collection, it will redirect to product list, where all the products of that clicked collection will be displayed.
Here is the sample query which I used to get the products list of particular collection :
{
collectionByHandle(handle: "") {
products(first: 10) {
edges {
node {
id
title
}
}
}
}
}
Now, I want filtering on products list. I want to display products base on product_type. But there is no any option to filter the products.
query option only available when you retrieve simple products listing using this query :
{
products(query: "product_type:casual-things", first: 10) {
edges {
node {
id
title
productType
}
}
}
}
But, this query option not available on products node of collectionByHandle.
Can, anyone help me how to implement filter option using Shopify storefront graphQL api in collectionByHandle query ?
The products connection doesn't have a query argument. You have basically access to fetching all products within that collectionByHandle and then filtering them client-side. You must have to use liquid for these types of nested features.

Best practice for schema naming of entity/collection

I am building a Graphql Schema and I was wandering what is the best practice of returning single vs collection items of a type. Let's say we want to retrieve users,
One option (if possible somehow) would be to have a query like this where the ID is optional, if ID is passed we return a single item, if not a collection of all users
query {
user (id: 1234) {
name
}
}
// return a single [User]
query {
user (id: null) {
name
}
}
// return a collection [User,User,User,...]
Another option would be to have user and users
query {
user (id: 1234) {
name
}
}
// return a single User
query {
users {
name
}
}
// return a collection [User,User,User,...]
I was wondering what is the best practice, or if you can pin-point me some resources related to that to read.
I am using the singular and plurals nouns to name the query field that return a single object and a list of object respectively. I think this naming style is very natural to most of the developers.
So to return a single user, it is :
type Query {
user(id:Int!) : User
}
It always return a single user. Just make the id input parameter as mandatory such that it cannot accept NULL.
And to return a list of user , normally it is:
type Query {
users : [User]
}
But in case it can have many users , most probably you need to consider something like pagination that allows developers to get the user page by page. For the offset -based pagination , I am doing something like below :
type Query {
users(offset:Int limit:Int) : UserPage
}
type UserPage {
data : [User]
pageInfo : PageInfo
}
type PageInfo {
# When paginating forwards, are there more items?
hasNextPage : Boolean!
# When paginating backwards, are there more items?
hasPreviousPage: Boolean!
# Total number of records in all page
total : Long
}
Depending on the requirements , you can consider to add an orderBy or a filter input parameter to the users query field to provide more options to the developers to get the result set that they are interested.
If you want to return the user list in the cursor-based pagination style, you can take a look on Relay Specification.

GraphQL with apollo-client, Is it possible to have same id's and different typenames

I had a question and can't find it in documentation.
For example I have a list
products with ids 1,2,3,4
And I have another list, categories with ids 1,2,3,4.
example query
{
products {
id
name
categories {
id
name
}
}
}
We can see that they both have same ids but different typename inside apollo.
Will it create any problem while caching the data? As Apollo normalizes our data with the id's,
Help would be appreciated.
Apollo normalizes using both the __typename and id (or _id) fields, so having a Product and a Category with the same id will normally not cause any problems.
The client normally appends the __typename for every selection set in your query -- so you do not have to actually add the __typename field yourself.
The config object passed to InMemoryCache includes a addTypename property, which defaults to true. If you set this to false, then the __typename field will not be added and you will see issues with the cache in this scenario unless you have universally unique IDs.

Resources