travis-r6s / gridsome-source-shopify

Shopify source plugin for Gridsome
https://gridsome-shopify-starter.netlify.com
MIT License
16 stars 14 forks source link

Add sortKey to sort products in collection query #39

Closed chrispreisler closed 4 years ago

chrispreisler commented 4 years ago

Hey,

is it possible to add the possibility to add the sortKey option, so we can sort products in collection queries, based on the options Shopify offers?

https://shopify.dev/docs/storefront-api/reference/object/productcollectionsortkeys?api[version]=2020-01

query Collection ($id: ID!) {
  shopifyCollection (id: $id) {
    id
    title
    products (sortKey: "MANUAL") {
      title 
    }
  }
}

Thank you very much for lookint into that.

Best regards Chris

travis-r6s commented 4 years ago

Sorry - will look at this soon, intend to add a few more features.

chrispreisler commented 4 years ago

Hey, just would like to know if you had the time to look into that? Would be really awesome, if you can integrate it. :) Cheers Chris

travis-r6s commented 4 years ago

Hey @chrispreisler - sorry for not getting back sooner.

I don't think it will be possible to do this, as once the data is in the Gridsome store, Gridsome handles the schema - I can't add anyway to sort it. You may have to sort it yourself in the client code.

chrispreisler commented 4 years ago

Hey @thetre97,

would it be possible to extend the query for collections with the products query and set there the sortKey to COLLECTION_DEFAULT? Then it would automatically take the sort setting, used in the collection.

I tested it with this example query in the Shopify GraphiQL App.

query {
  collectionByHandle(handle: "schals-tucher") {
    title
    products(sortKey:COLLECTION_DEFAULT, first: 10) {
      edges {
        node {
            title
        }
      }
    }
  }
}

Thanks again for looking into that.

Best regards Chris

chrispreisler commented 4 years ago

Also I need manual sorting and there is no possibility to get the manual sorting in any way in my client code as I understand it.

chrispreisler commented 4 years ago

As I understand your code, right now you are looping through all products and then add the product to the including collections. So the order of the products is only related to the whole product list and therefore never reflect the order of the collection.

Would it be possible to do it the other way. First create all products and then create the collections. And while you create the collections you loop through the product ids of the collection and create references to the products, so the order in the collection will be considered.

chrispreisler commented 4 years ago

Maybe you can have a look at this fork of me. I exactly did, what described above. The only thing is that I had to create a new collection.productList item to make it work, but maybe we can also overwrite the collections.products data.

https://github.com/chrispreisler/gridsome-source-shopify

Now I can query the products like this. And because I loop through the order of the products in the collection data, I get the right order.

query {
  allShopifyCollection(filter: { handle: { eq: "schals-tucher" } }) {
    edges {
      node {
        title
        productList {
          title
        }
      }
    }
  }
}

Would love to get your opinion on that.

chrispreisler commented 4 years ago

Hey @thetre97 I looked at my code again and cleaned everything up and now it takes the old products item in the graphql query. The only change is in the getCollection() function and the querie.js in the collection query to get the ids.

https://github.com/chrispreisler/gridsome-source-shopify/blob/master/src/index.js

travis-r6s commented 4 years ago

@chrispreisler The reason I didn't do it that way in the first place was because collections could have more than 250 products, so I would need to do a nested pagination query, and it was easier to just link them from the products side.

But if this sort order is essential, I can add it now and figure out the pagination part later 🙂

chrispreisler commented 4 years ago

The shop, I tested it with has more than 1000 products, also in one collection there are 899 products and in my local environment it has loaded and shows all 899 products. So maybe your code does that unintentionally?

travis-r6s commented 4 years ago

@chrispreisler Sure, it will show all products as they are still linked here: https://github.com/chrispreisler/gridsome-source-shopify/blob/15ab37d164473fc2484527453ddc6afe108c5a6b/src/index.js#L129

But if you removed that line so collection { products { id ... contains only sorted products (from https://github.com/chrispreisler/gridsome-source-shopify/blob/15ab37d164473fc2484527453ddc6afe108c5a6b/src/index.js#L101), it will only show the first 250 products...

chrispreisler commented 4 years ago

Sorry to be honest, I am not quite sure what you mean.

Because of this line it will always only contain sorted products, doesn't it? https://github.com/chrispreisler/gridsome-source-shopify/blob/15ab37d164473fc2484527453ddc6afe108c5a6b/src/index.js#L102

The count of products before and after the sorting won't change, as the products are the same, they are now just sorted the way they are sorted in shopify.

travis-r6s commented 4 years ago

Not at the moment, no, because of https://github.com/chrispreisler/gridsome-source-shopify/blob/15ab37d164473fc2484527453ddc6afe108c5a6b/src/index.js#L129. That bit of code is getting the Collection from store, and pushing the current product ID to the collection.products array.

So, if we implemented just your code changes, we would remove that above line, as we are already adding products in the collections loop (the code you added). Then, as we are only querying for the first 250 products in a collection https://github.com/chrispreisler/gridsome-source-shopify/blob/15ab37d164473fc2484527453ddc6afe108c5a6b/src/queries.js#L100, when we query a collection and the products inside it, it will only return 250 products. The number of ShopifyProduct nodes added to the store won't change, no, but the amount inside ShopifyCollection.products will.

Does that make sense? In any case, I will need to implement pagination support for nested fields.

chrispreisler commented 4 years ago

Okay, what I now understand as you also say that I first add the product ids to collection.products in line 129 and then in line 102. So for example when I have 700 products in the collection "clothing" there are now 950 product ids in collection.products, when I log the lenght of products, while starting gridsome via "gridsome develop".

But now there is something really strange happening. When I log the count for the products in Collection.vue via " console.log(this.$page.shopifyCollection.products.length);" I get the right length of 700 and even more weird I get all 700 products in the sorting order defined in the shopify system.

Is Gridsome getting rid of duplicates automatically or is there any gridsome magic happening?

chrispreisler commented 4 years ago

You are also right, that the best way to do this, would be to nested load the products in the collection query. I created a first draft with a new getCollectionAll function in client.js. In the end it ist doing the same like you are doing for nested loading with the top level queries. But right now it is its own function just for collections. Maybe we find a more elegant way to do this.

https://github.com/chrispreisler/gridsome-source-shopify/blob/master/src/client.js#L55

chrispreisler commented 4 years ago

I looked at it again and overhauled the query functions. So now there are only the queryOnce and queryAll and two helper functions getNodes and queryCollectionProducts.

https://github.com/chrispreisler/gridsome-source-shopify/blob/master/src/client.js#L31

travis-r6s commented 4 years ago

Hey, sorry - thanks for those suggested changes, will try to look at them this week...

travis-r6s commented 4 years ago

Hey @chrispreisler, so sorry for the delay on this. Finally implemented it though! Just released v0.2.0 which contains this update. If you are still using this plugin, let me know if you have any issues with the updates...

I should be able to expand it to other types to in the future, should I need to.

chrispreisler commented 4 years ago

Hey @thetre97,

I used my version of the plugin, but wanted to switch to your version. Thank you very much for implementing it.

Unfortunately I get this error, when starting the dev server with "gridsome develop". The shop has around 1000 products.

Error: Timeout
    at Object.paginate (/Users/chrispreisler/Dropbox/Local Development/hundred-hands-2020/node_modules/gridsome-source-shopify/lib/index.js:342:27)
    at AsyncGeneratorFunction.paginateEach [as each] (/Users/chrispreisler/Dropbox/Local Development/hundred-hands-2020/node_modules/gridsome-source-shopify/node_modules/got/dist/source/create.js:197:47)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async queryAll (/Users/chrispreisler/Dropbox/Local Development/hundred-hands-2020/node_modules/gridsome-source-shopify/lib/index.js:358:37)
    at async ShopifySource.getProducts (/Users/chrispreisler/Dropbox/Local Development/hundred-hands-2020/node_modules/gridsome-source-shopify/lib/index.js:595:25)
    at async /Users/chrispreisler/Dropbox/Local Development/hundred-hands-2020/node_modules/gridsome-source-shopify/lib/index.js:531:7
    at async Plugins.run (/Users/chrispreisler/Dropbox/Local Development/hundred-hands-2020/node_modules/gridsome/lib/app/Plugins.js:141:11)

Maybe you find the time to look into this one.

Thanks a lot for your effort.

Best regards Chris

travis-r6s commented 4 years ago

Yes, I've been having that issue recently as well - think it's to do with their rate-limiting: https://shopify.dev/docs/storefront-api/getting-started#storefront-api-rate-limits (I looked at the Gatsby plugin, and it has similar issues). Does the previous version of this plugin work okay? If so, I have just published v0.2.4, which adds a longer timeout, and changes perPage back to 100 - this may help.

travis-r6s commented 4 years ago

Also probably linked with #49

chrispreisler commented 4 years ago

Yes I think you are right, I updated to the latest version and now everything is working as expected. Thanks again for your help.