Shopify GraphQL Pagination Without Using Cursor - graphql

I have read the tutorial for pagination using the parameter after:cursor in this article https://shopify.dev/concepts/graphql/pagination. Unfortunately, I cannot use this because I want to generate a sitemap for all the products. As you know, we can only get 250 products maximum at a single graphql request. What I am building is something like this:
sitemaps/products-1-250.xml
sitemaps/products-251-500.xml
sitemaps/products-501-750.xml
and so on...
I want to make some query like this where I can get products from 251 to 500:
query GetAllProductsForSitemap {
products(first: 250, page: 2) {
edges {
node {
id
title
other-attributes
}
}
}
}
But of course, page is not a valid parameter.
Is this achievable in Shopify-GraphQL?

Why don't you just take the perfect sitemap for all your products that are generated for free for you by Shopify? Any reason you are re-inventing the wheel?
As for your request, the short answer is no. One uses cursors when using the GraphQL API for data. Alternatively, you are 100% free to use paging with the RestAPI, so if you have to, you can.

Related

Retrieving images from Contentful -Not seeing child image sharp in graphql playground

I am still new to Gatsby and Graphql and am trying to go through tutorials of using gatsby-transformer-sharp, gatsby-plugin-sharp, and gatsby-plugin-image to retrieve images from Contentful using graphql and map over those images. In all of the tutorials I have read and watched, they have the option of "child image sharp" in their playground and I do not have that.
This is what graphql looks like
This is what my plugins look like
Would someone be able to help or walk me through how my query should look and how to map over that data in the query to retrieve those images?
Thank you so much!
It depends on when are those tutorials done or recorded. Gatsby image has suffered a lot of breaking changes since its creation (see migration Gatsby 2 to 3) changing from gatsby-image to gatsby-plugin-image.
As you can see in gatsby-source-contentful docs you don't always need childImageSharp. It depends on the node you are quyering:
{
allContentfulCaseStudy {
edges {
node {
id
slug
title
subtitle
body {
body
}
heroImage {
title
description
gatsbyImageData(layout: CONSTRAINED)
# Further below in this doc you can learn how to use these response images
}
}
}
}
}
Source: gatsby-source-contentful docs
As long as your GraphQL contains gatsbyImage and gatsbyImageData means that the transformers (gatsby-transformer-sharp) and sharps (gatsby-plugin-sharp) are doing their job.
Your query will rely on your data structure, check the tutorials to understand better, keeping in mind that your data will be under props.data.allContentfulCarousel of the page, but it looks that Images is an array of images, hence you will need to make another loop through it in order to render the GatsbyImage component passing each image.

Gatsby graphiQL - Cannot return null for non-nullable field ImageSharpFluid.src

I'm using Gatsby and graphql with headless WordPress for a website.
I want to use a gatsby-image plugin to get srcSet and blurring effect for images that are coming from WordPress, but it throws an error in graphiQL playground. I want to explain below the whole process step by step for the best understanding.
The gatsby-image plugin has two types of responsive image fixed and fluid:
To decide between the two, ask yourself: “do I know the exact size this image will be?” If yes, it’s the first type. If no and its width and/or height need to vary depending on the size of the screen, then it’s the second type.
so, I need the second one - fluid.
It also has two image components Static and Dynamic.
If you are using an image that will be the same each time the component is used, such as a logo or front page hero image, you can use the StaticImage component.
If you need to have dynamic images (such as if they are coming from a CMS), you can load them via GraphQL and display them using the GatsbyImage component.
I'm using WordPress (which is CMS). So, I need the second one - Dynamic
Before writing a query, I must see how to make the right query for the files coming from the WordPress scheme.
For this reason, I found that Gatsby has a gatsby-source-wordpress plugin to pull images from WordPress.
I've installed and configured all the required packages such as gatsby-plugin-image,gatsby-plugin-sharp, gatsby-transformer-sharp, etc. I did Everything as exactly as the official docs say.
At that time everything was prepared to make a query, so I try the first example that they have in docs - pulling images from wordpress and IT WORKED.
So it's time to FINALLY GET WHAT I WANTED and try the second example (fluid), but IT FAILED with an error message Cannot return null for non-nullable field ImageSharpFluid.srcSet.
It also FAILS when I try to get gatsbyImageData
How could I fix this problem?
Thanks in advance.
The documentation you mention for gatsby-source-wordpress is outdated. Checkout this one: https://www.gatsbyjs.com/plugins/gatsby-source-wordpress/
Your query looks like the old one. I'm not sure what plugin versions you are running, but if you are running the latest ones your query should look something like this:
query MyQuery {
allWpPost {
nodes {
featuredImage {
node {
localFile {
childrenImageSharp {
gatsbyImageData(width: 200, placeholder: BLURRED, formats: [AVIF, WEBP, JPG])
}
}
}
}
}
}
}
Also the gatsby-image plugin is deprecated in favor of gatsby-plugin-image.
If you want an example of how the setup is put together you can search the starters for CMS:WordPress and v3 to find one to start with. Gatsby Starters
Hope this gets you started :)
If You have used caching in your plugin options like the code below, Try deleting the .cache folder in your workspace and restart the server.
{
resolve: `gatsby-source-wordpress`,
options: {
production: {
hardCacheMediaFiles: true,
},
},
},
Probably It would take time fetching the images and then your page should load without any errors.

Shopify Storefront API: Getting referenced variant with GraphQL

I'm using the Shopify Storefront API and Accentuate to try to get my hands on a specific variant, but it won't work for me.
THE SHORT VERSION: When I select a variant on the website, I get the url: (... url ...)?variant=31696763027492. How do I get my hands on these numbers after the = for the variant in GraphQL? It does not match the ID.
THE LONG VERSION...
In a product variant, I reference to a variant of another product (with Accentuate). What I need to get out is the variant that I am referencing to.
When I pull out the variant that is being referenced to in the product (as metafield, with GraphQL), I get this:
{
"key": "products_in_package",
"value": "pakke-produkt-gavepose:31696763027492"
}
My problem is the numbers after : in the value. I've found that these are the number that come after the URL of the product when selecting the variant on the "actual" Shopify website ((... url ...)?variant=31696763027492), but I can't see how I can use them, since I can't find these numbers on the actual variant through GraphQL.
It does not match the 'id' or anything else I could find on the variant. Neither can I include the numbers if I try to get productByHandle.
So, does anyone have any ideas on how I can I use it to get the actual product variant through GraphQL? Or ideas on what else I can do to connect a specific product variant to another product variant?
The storefront API and admin API return different format of Id
storefront API: "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzQ3NjA3ODY1MDE3MDM="
Admin API: "gid://shopify/Product/4760786501703"
But there is a convert way between each other, use function atob
atob("Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzQ3NjA3ODY1MDE3MDM=") will get the Admin API Id
For NodeJS package: https://www.npmjs.com/package/atob
The variant ID and GraphQL variant ID is closely related.
Variant id - 31646396055604
GraphQL Variant id - gid://shopify/ProductVariant/31646396055604
The GraphQL ID is the same as the Variant id but you must add the string gid://shopify/ProductVariant/ before it.
So your GraphQL request will become like so:
{
productVariant(id:"gid://shopify/ProductVariant/31646396055604"){
title
product{
id
}
}
}
The problem is (or was) that those numbers are not what you get when you get the id from the product through GraphQL. You get a much longer id, like "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8zMTY5NDA3MjQxNDI0NA==".
However, I figures out that using the btoa() JavaScript function on the id you mention (gid://shopify/ProductVariant/31646396055604), I got the long id that I get from the product itself. So problem solved!

Apollo Client: can apollo-link-rest resolve relations between endpoints?

The rest api that I have to use provides data over multiple endpoints. The objects in the results might have relations that are are not resolved directly by the api, it rather provides ids that point to the actual resource.
Example:
For simplicity's sake let's say a Person can own multiple Books.
Now the api/person/{i} endpoint returns this:
{ id: 1, name: "Phil", books: [1, 5, 17, 31] }
The api/book/{i} endpoint returns this (note that author might be a relation again):
{ id: 5, title: "SPRINT", author: 123 }
Is there any way I can teach the apollo client to resolve those endpoints in a way that I can write the following (or a similar) query:
query fetchBooksOfUser($id: ID) {
person (id: $id) {
name,
books {
title
}
}
}
I didn't try it (yet) in one query but sould be possible.
Read docs strating from this
At the beggining I would try with sth like:
query fetchBooksOfUser($id: ID) {
person (id: $id) #rest(type: "Person", path: "api/person/{args.id}") {
name,
books #rest(type: "Book", path: "api/book/{data.person.books.id}") {
id,
title
}
}
}
... but it probably won't work - probably it's not smart enough to work with arrays.
UPDATE: See note for similiar example but using one, common parent-resolved param. In your case we have partially resolved books as arrays of objects with id. I don't know how to use these ids to resolve missing fields () on the same 'tree' level.
Other possibility - make related subrequests/subqueries (someway) in Person type patcher. Should be possible.
Is this really needed to be one query? You can provide ids to child containers, each of them runing own query when needed.
UPDATE: Apollo will take care on batching (Not for REST, not for all graphql servers - read docs).
'it's handy' to construct one query but apollo will cache it normalizing response by types - data will be stored separately. Using one query keeps you within overfetching camp or template thinking (collect all possible data before one step rendering).
Ract thinking keeps your data and view decomposed, used when needed, more specialised etc.
<Person/> container will query for data needed to render itself and list of child-needed ids. Each <Book/> will query for own data using passed id.
As an alternative, you could set up your own GraphQL back-end as an intermediary between your front-end and the REST API you're planning to use.
It's fairly easy to implement REST APIs as data sources in GraphQL using Apollo Server and a package such as apollo-datasource-rest which is maintained by the authors behind Apollo Server.
It would also allow you to scale if you ever have to use other data sources (DBs, 3rd party APIs, etc.) and would give you full control about exactly what data your queries return.

Get all members from the mailing list using MailChimp API 3.0

http://kb.mailchimp.com/api/resources/lists/members/lists-members-collection
Using this resource we can obtain only first 10 members. How to get all?
The answer is quite simple - use offset and count parameters in URL query:
https://us10.api.mailchimp.com/3.0/lists/b5b5fdc2fa/members?offset=150&count=10
Finally I found PHP API client for MailChimp API v3:
https://github.com/pacely/mailchimp-api-v3
And official docs about pagination.. I missed it before :(
http://kb.mailchimp.com/api/article/api-3-overview
I stumbled on this one while researching a way to get all list members in MC API 3.0 as well. I noticed that there were some comments on the API timing out when trying to get all list members on one page. I also encountered this at first but was able to overcome it by limiting the fields in the result by using the 'fields' param. My code is for a mass deleter so all I really needed was the ID of each member to put together a batch delete request. Here's how my fetch request looks (psuedo-code):
$total_members = $result['total_items'];//get number of members in list via previous request
https://usXX.api.mailchimp.com/3.0/lists/foobarx/members?fields=members.id&count=total_members
This way I'm able to fetch over 15,000 subscribers on one page without error.
offset and count is the official way on the docs, but the problem is that has linear slowdown. It appears to be an n^2 solution, so if you have 20,000 items, you're in trouble. Their docs http://developer.mailchimp.com/documentation/mailchimp/reference/lists/members/#read-get_lists_list_id_members warn you against using offset.
If you're scenario permits you to use other filters (like since_last_changed), then you can do it quickly. See What is the right syntax for "timeframe" in MailChimp API 3.0 for format for datetime.
Using offset and count parameters are correct as mentioned in some of the other answers, but becomes tedious for large lists.
A more efficient way, is to use a client for the MailChimp API. I used mailchimp3 for python. Using this, it's pretty easy to get all members on your list because it handles the pagination. Here's how you would do it.
from mailchimp3 import MailChimp
client = MailChimp('YOUR_USERNAME', 'YOUR_SECRET_KEY')
client.lists.members.all('YOUR_LIST_ID', get_all=True, fields="members.email_address")
You can do it just with count, making an API call to the list root so in the next API call you include the count parameter and you have all your list members.
I ran into issues with this because I had a moderate list with 2600 members and MailChimp was throwing an error, but it worked with 1500 people.
So for a list bigger than 1500 members I use MailChimp export API bare in mind that this is going to get discontinued but I could not find any other acceptable solutions.
Alternatively for bigger lists (>1500) you could get the total of members and then make multiple api calls to the Member endpoint but I really dislike that :(
If anyone has a better alternative I would be really glad to hear it.
With MailChimp.Net.
Use the offset value.
List<Member> listMembers = new List<Member>();
IMailChimpManager manager = new MailChimpManager(MailChimpApiKey);
bool moreAvailable = true;
int offset = 0;
while (moreAvailable)
{
var listMembers = manager.Members.GetAllAsync(yourListId, new MemberRequest
{
Status = Status.Subscribed,
Limit = 250,
Offset = offset
}).ConfigureAwait(false);
var Allmembers = listMembers.GetAwaiter().GetResult();
foreach(Member member in Allmembers)
{
listMembers.Add(member);
}
if (Allmembers.Count() == 250)
//if the count is < of 250 then it means that there aren't more results
offset += 250;
else
moreAvailable = false;
}

Resources