Shopify Graphql how to get available products for specific collection based on location - graphql

Shopify GraphQL. I want to have a list of products for specific collection based on location.
Expectrd list of products.
I tried:
query($collectionId: ID!, $locationId: ID!) {
collection(id: $collectionId) {
products(first: 50) {
edges {
node {
id
title
availableForSale
images(first: 50) {
edges {
node {
id
altText
originalSrc
}
}
}
variants(first: 50, query: "location_id:$locationId") {
edges {
node {
id
title
inventoryQuantity
sku
}
}
}
}
}
}
}
}
But I have an error for variants not support query

It is true. Variants do not in fact have a location. But they do have an inventory item ID. And when you leverage that, you'll find you can get the inventory levels of any particular inventory item ID at locations.
So if you were to extract the availability of an item at a location, ie) a variant, you would also know that the product the variant belongs to, is stocked at that location.
Your approach of starting with a collection, and then getting the products in that collection, and then getting the variants of each product, and then checking if the variant is stocked at one or more locations, is really really clunky.
I think instead you should extract the inventory at each location. That would then give you products. With those products you might be able to create a collection to hold them. But since location is not a criteria, you're going to have to make up something.

Related

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.

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.

Gatsby.js: Filter GraphQL query by nested object property

I'm working on a news site which will have articles, each with one or multiple respective authors. If you click on an author's name, it will take you to a page displaying their information and a list of articles they have contributed to.
So each article has an authors property, which in turn is an array of author objects with properties: full name, slug (lowercase version of full name with spaces replaced by dashes), etc.
Is it possible to filter the articles by a particular author's slug when defining the query?
query authorQuery($slug: String!) {
allContentfulArticle(filter: { //not sure what to do here }) {
edges {
node {
title
slug
authors {
name
slug
}
}
}
}
}
My other option would be to load all of the articles, then setup a filter in the component like so:
const articles = data.allContentfulArticle.edges.filter(({ node }) => {
return node.authors.some((author) => author.slug === data.contentfulAuthor.slug);
});
This wouldn't be the end of the world, however it goes against the GraphQL principle of only loading the data you need.
What you want to achieve here if I understood correctly, you want to group articles by author.
You can achieve that if you query and apply filter to allContentfulAuthor
and request the article field, like so:
{
allContentfulAuthor(filter: {slug: {eq: "myslug"}}) {
edges {
node {
name
article {
title
slug
}
}
}
}
}
Note that the article name is your contentTypeId for your articles.

Apollo/React mutating two related tables

Say I have two tables, one containing products and the other containing prices.
In Graphql the query might look like this:
option {
id
price {
id
optionID
price
date
}
description
}
I present the user with a single form (in React) where they can enter the product detail and price at the same time.
When they submit the form I need to create an entry in the "product" table and then create a related entry in the "price" table.
I'm very new to Graphql, and React for that matter, and am finding it a steep learning curve and have been following an Apollo tutorial and reading docs but so far the solution to this task is remaining a mystery!
Could someone put me out of my misery and give me, or point me in the direction of, the simplest example of handling the mutations necessary for this?
Long story short, that's something that should actually be handled by your server if you want to optimize for as few requests as possible.
Problem: The issue here is that you have a dependency. You need the product to be created first and then with that product's ID, relate that to a new price.
Solution: The best way to implement this on the server is by adding another field to Product in your mutation input that allows you to input the details for Price as well in the same request input. This is called a "nested create" on Scaphold.
For example:
// Mutation
mutation CreateProduct ($input: CreateProductInput!) {
createProduct(input: $input) {
changedProduct {
id
name
price {
id
amount
}
}
}
}
// Variables
{
input: {
name: "My First Product",
price: {
amount: 1000
}
}
}
Then, on the server, you can parse out the price object in your resolver arguments and create the new price object while creating the product. Meanwhile, you can also relate them in one go on the server as well.
Hope this helps!

GraphQL: Filter data in an array

I'm sure it's a simple thing to do, but I couldn't find anything in either GraphQL's doc or Graphcool's.
Say I have an entity with this schema (new GraphQL user, sorry if I make mistake in the schema representation):
Book {
name: String!
author: String!
categories: [String!]
}
How would I do a query for all books that are part of the "mystery" category? I know I can filter with allBooks(filter: {}), but categories_in: ["mystery"] and categories_contains: "mystery" didn't do the trick.
Category model
Thinking a bit more about this situation, creating a Category model is definitely the way to go.
For example, imagine you want to allow readers to subscribe to their favorite categories later. Or, what if you want a list of all existing categories? Using string lists, you would need to query all books and somehow postprocess all obtained categories. Handling this on a model level rather than using string lists feels much more natural.
Instead, you can create a new Category model and add a many-to-many relation between Category and Book. In situations like this, I like to add a unique enum field tag and a string field text. (A unique string field tag alone would also be suitable, probably a matter of taste.)
With this setup, you can easily fulfill data requirements like
Which books are assigned to a given category?
query {
# query books by unique category tag
Category(tag: MYSTERY) {
books {
id
}
}
# query books by specific category text
Category(filter: {
text: "mystery"
}) {
books {
id
}
}
}
Which books are assigned to at least one category of a given list?
query {
allCategories(filter: {
OR: [{
tag: MYSTERY
}, {
tag: MAGIC
}]
}) {
books {
id
}
}
}
Which books are assigned to all categories of a given list?
query {
allCategories(filter: {
AND: [{
tag: MYSTERY
}, {
tag: MAGIC
}]
}) {
books {
id
}
}
}
Related filters
Even though the above queries fulfill the specified data requirements, books are grouped by Category in the response, meaning that we would have to flatten the groups on the client.
With so called related filters, we can turn that around to only obtain books based on conditions defined its related categories.
For example, to query books assigned to at least one category of a given list:
query {
allBooks(filter: {
OR: [{
categories_some: {
tag: MYSTERY
},
categories_some: {
tag: MAGIC
}
}]
}) {
id
}
}
If you are interested in using a hosted GraphQL service, scaphold.io has had this feature for a while now. All connection fields in your API come with a WhereArgs argument that exposes filters that let you really dig into your data. When you have a list of scalars like this, the WhereArgs include a contains & notContains field that allow you to filter results based off the values in your list. This allows you to make a query like this.
query MysteriousBooks($where:BookWhereArgs) {
viewer {
allBooks(where:$where) {
edges { node { title, ... } }
}
}
}
# Variables
{
"where": {
"categories": {
"contains": "mystery"
}
}
}
Just to be complete, you could also do a slight schema readjustment to make this work without having to filter on a scalar list. For example, you could make Category a node implementing type and then create a connection between Category and Book. Although a Book will likely not have many categories, this would allow you to issue a query like this:
query MysteriousBooks($where: CategoryWhereArgs) {
viewer {
allCategories(where: $where) {
books {
edges { node { title, ... } }
}
}
}
}
# Variables
{
"where": {
"name": {
"eq": "mystery"
}
}
}
If you structure your schema this way then you would also be able to do more filtering on the books in the category without having to loop through every book in your archive. E.G. you could efficiently ask for "all the mystery books written in the last year."
Full disclosure: I work at Scaphold and although I'd love you to try it out no hard feelings if you don't switch over. I'm excited to see people trying and loving GraphQL. If you're curious about how to implement this type of behavior on your own server let me know and I'd be happy to help there as well!
I hope this helps!

Resources