GraphQL Shopify query and sorting - graphql

We currently have a setup where customers can sort products on price, title, created, manual, etc. Every time there's a query like
`query ($handle: String!, $numProducts: Int!, $sortKey: ProductCollectionSortKeys!, $reverse: Boolean!) {
collectionByHandle(handle: $handle) {
id
handle
description
descriptionHtml
title
image {
id
originalSrc
altText
}
products(first: $numProducts, sortKey: $sortKey, reverse: $reverse) {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {...
`
There are 8 queries in total, one for each sortKey. The idea is to move the sorting logic to js, making a single query instead of 8.
The problem is, I can only do 7 types of sorting in javascript (PRICE, TITLE, CREATED (ascending and descending)), and either MANUAL or BEST_SELLING.
To get both MANUAL and BEST_SELLING, I currently will have 2 queries, which is already an improvent!
Is there a way to combine them into a single query, a bit like mySql, creating a 'virtual' field e.g. manual_sort_position: 5 to add to a product?

Related

Hasura complex search of products

How can i solve this problem with complex searching in products?
This is what i have now as a standard get products and search on them.
query getProducts($limit: Int, $offset: Int, $searchQuery: String) {
products_products(limit: $limit, offset: $offset, where: {_or: [{title: {_ilike: $searchQuery}}, {shortDescription: {_ilike: $searchQuery}}], active: {_eq: true}}) {
__typename
id
shortDescription
title
likes {
userId
}
images(where: {main: {_eq: true}}) {
image
}
categories {
category {
title
}
}
}
}
i have products table, categories table, join table(productId, categoryId), later on there would be reviews table, wishlist table
how to show products only in any category (record in join table)?
how to show products with reviews 3.5+ ?
You know how it is with complex filtration.
Can someone show me how it could be done?
Lastly .. im using flutter with optimistic results, so thats why i chose this structure of query. it makes sense when "replicating" the state of wishlist.
how to show products only in any category (record in join table)?
You can filter on related data as well
query {
product(where: { category: { name: { _eq: "Kitchen" } } })
}
how to show products with reviews 3.5+ ?
I assume you mean an average review of 3.5 stars or greater?
There is a brand new feature in Hasura called Aggregation Predicates that lets you do this
See last month's community call demo for how to use it:
https://youtu.be/4LUiztVe8EA?t=1505
By the way, if you are building an e-commerce type application, there is a sample application which already implements much of this functionality so you can see how it is done:
https://hasura.io/reference-app/
https://github.com/hasura/hasura-ecommerce

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.

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

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.

GraphQL: Is it possible to search nested field?

I am specifically using the shopify graphql admin api to query orders.
I want to do a search for a nested related field.
Below is my query.
export const orderHistoryQuery = gql`
query Order($productsFirst: Int!, $productsAfter: String, $filterQuery: String) {
orders(first: $productsFirst, after: $productsAfter, reverse: true, query:$filterQuery) {
edges {
cursor
node {
id
name
customer {
id
metafields(first: 10) {
edges {
node {
id
key
value
namespace
}
cursor
}
}
}
totalPriceSet {
shopMoney {
amount
currencyCode
}
}
subtotalPriceSet {
shopMoney {
amount
currencyCode
}
}
totalRefundedSet {
shopMoney {
amount
currencyCode
}
}
currencyCode
email
phone
processedAt
totalShippingPriceSet {
shopMoney {
amount
currencyCode
}
}
totalTaxSet {
shopMoney {
amount
currencyCode
}
}
shippingAddress {
firstName
lastName
address1
address2
city
province
zip
country
}
billingAddress {
firstName
lastName
address1
address2
city
province
zip
country
}
customAttributes {
key
value
}
}
}
}
}
`;
I want to query metafields or ANYTHING really but it doesn't seem like it's supported. I am not sure if I just have the wrong query syntax or if it's not supported. The shopify search syntax documenation doesn't really help and this is where my knowledge of graphql falls apart.
Is it possible to do this in graphql? I also tried adding metafields(id: $whateverID) which is not supported by their setup.
Unfortunately, Shopify doesn't support query filters on metafields. The best way to figure this out is by using a graphql explorer like GraphiQL. Shopify dashboard has this built in if you go to Apps > Shopify GraphiQL App.
Using GraphiQL you can see that:
Customers query doesn't have metafields supported:
Orders query doesn't have customers or metafields supported:
And metafields on customers doesn't have a query param:
I think your options are to either query by what you can and filter after you get the results or use a customer tag and query by tag.
You would really help your cause out by simplifying things. My advice to you is to try a simple query. Can you get an order? Since an order has a customer (usually but not always), can you get a metafield associated with that customer?
You have so many obstacles in your attempt to show what you are trying to do, it is almost as if you want a migraine headache in trying to debug anything. GraphQL calls to endpoints are documented fairly well from the GraphQL website perspective, and Shopify is nothing but a vanilla implementation of that, with the caveat that they charge you for calls based on complexity, so you had best be monitoring your credits.
So ya, try simple calls. Get a product and it's Metafields. Get a customer record and it's Metafields. If you can do that, you are not challenging the documentation much, nor the concept of GraphQL queries. Once a basic all works, you can work in variables, cursors, paging, etc... but until a one-off call gives you what you want, debugging should be concentrated on the simplest of calls, not everything and the kitchen sink.
Also, when you screw up a call to the endpoint, Shopify usually returns a response with details about where you screwed up, providing you with a first place to look. We see nothing of your response, so there is little to go on to help you.

GraphQL with multiple objects: should I keep all objects in a single query?

I´m building a SaaS B2B application composed of several different objects. Examples:
Users
Customers
StockItens
StockLevels
PriceList
Sales
Returns
Etc...
I´ll have around 40 different objects, that can be listed and created, edited, and deleted individually.
Facing the GraphQL concepts for the first time, should I build a large schema for all objects, like the example below, or should I keep each object on its own query.
query {
viewer {
Users {
id
firstName
lastName
address
city
...
}
Customers {
id
firstName
lastName
address
city
rating
...
}
StockItens {
id
item_id
sales {
id
dateTime
qty
unitValue
totalValue
...
}
...
}
StockLevels {
...
}
PriceList {
...
}
Sales {
id
dateTime
qty
unitValue
totalValue
...
}
Returns {
...
}
}
}
Looking for the first option (keeping everything into one single query) seens logical as I will be using fragments to access the desired piece of information, but then I will have a huge schema with lots of inter relations.
PLease advice what would be the best practice on that use case.
I suggest you do not write a query where you add all needed data but use the concept of fragments as you already pointed out.
And you fetch only the data which are needed for the current page. So the throughput is kept minimal.
e.g.
If you have a page where you update a user you just fetch the needed data for this user in a specialized query. The query consists of fragments.
The fragments are related to the subcomponents which are used in the page, for example a form where you show the data of the user.
The fragment of the form defines the data it needs from the user and the update page combines the fragments to the query.
// in user form component
const userFormFragments = {
name: "UserForm",
document: `fragment UserForm on User {
id
name
}`
};
// in update user page
const userQuery = `query getUserQuery($userId: ID!) {
getUser(userId: $userId) {
...${userFormFragment.name}
}
${userFormFragment.document}
}`

Resources