Get ANY product by ID in liquid - seems it can not be done without overly elaborate methods?

Get ANY product by ID in liquid - seems it can not be done without overly elaborate methods?

cfc_webmaster
Explorer
47 0 126

Consider the following scenario:

I have a custom JSON array metafield added to products like so to highlight hotspots on an image:

 

{
  "my_json_array": [
    {
      "settings": {
        "my_product_id": 1000090788054,
        "x_axis_id": 17,
        "y_axis_id": 55
      }
    },
    {
      "settings": {
        "my_product_id": 1000090853590,
        "x_axis_id": 61,
        "y_axis_id": 51
      }
    },
    {
      "settings": {
        "my_product_id": 1000090919126,
        "x_axis_id": 30,
        "y_axis_id": 36
      }
    },
    {
      "settings": {
        "my_product_id": 1000090886358,
        "x_axis_id": 85,
        "y_axis_id": 34
      }
    }
  ]
}

 

 

In theory all I should have to do in Liquid to GET that product...

could be as elegant and simple as this:

 

{% for hotspot in my_json_array %}
{% assign this_product = all_products[hotspot.settings.my_product_id] %}
{{ this_product.title }}
{% endfor %}

But that 'not work'...

 

Lets then examine some methods to GET any product by ID

 

OPTION #1

 

{% for product in collections.all.products %}
  {% if product.id == 1000090788054 %}
     {% assign this_product = product %}
  {% endif %}
{% endfor %}

FLAWED: because collections.all.products is limited (not really the full catalog, limited to 10-100 I think)

 

###

 

OPTION #2 

{% for product in collections.all.products %}
{% case product.id %}
{% when 1000090788054 %}
{% assign this_product = product %}
{% endcase %}
{% endfor %}

FLAWED: because again collections.all.products is limited (again, not the full catalog)

 

###

 

OPTION #3

{%- liquid
paginate collections.all.products by 1000
for product in collections.all.products
if product.id == 1000090788054
assign this_product = product
endif
endfor
endpaginate
-%}

WORKS...

BUT FLAWED: because now collections.all.products is looping through 1000 products via an overly elaborate method to paginate, and if the catalog go's above 1000 we are going to have a problem.

 

Note- perhaps my concern here for server load, efficiency and speed is a mis-qualified unfounded fear?

In other words: can I go above paginate by 1000, lets say paginate by 25,000 ?

 

Should I just 'not worry' about efficiency and speed of a shop?

(So far, this does not seem to slow the template down)

 

###

 

Observations:

  1. GET a product by HANDLE is the worst possible way to set this up (because handles change)
  2. GET any product by a unique ID is the best possible way to approach any catalog or database
  3. Forcing us to loop over a 1000 catalog pagination seems vastly inefficient and illogical

###

 

A good question:

How else am I supposed to GET just 1 single product by ID when I have the ID value of that product?

 

My conclusion:

There is NO OTHER WAY to accomplish this task (other than Option #3 for a large catalog up to 1000 products)

 

Furthermore, once a catalog reaches greater than 1000+ products its then going to be a problem to just get 1 product in Liquid and I will have a worse problem.

 

  • Is my conclusion correct?
  • Is there a better more efficient way to do this in a custom Liquid section/snippet?
  • Why would Shopify not make GET product by ID available in Liquid
  • Why would Shopify only make GET product by HANDLE if the HANDLE can change?
  • Surely there is a way to GET a product by ID from collections.all.products without a loop?
  • Are my concerns unfounded?
Replies 4 (4)

PaulNewton
Shopify Partner
7721 678 1626

 

@cfc_webmaster wrote:
GET a product by HANDLE is the worst possible way to set this up (because handles change)

GET any product by a unique ID is the best possible way to approach any catalog or database

Forcing us to loop over a 1000 catalog pagination seems vastly inefficient and illogical

These are key flaws and assumptions.

Your assuming a product id is permanent and cannot be deleted ,  and ignoring that a product may be duplicated getting a new id and a new handle .

Your assuming the frontend of a shopify store is a database, this is not SQL, php,ruby or even javascript.

The view of illogically having to loop over 1000 items is based on the bad previous assumptions leading to that viewpoint. 

 

Whatever is generating that JSON and getting shopify-product-ids should be just as capable of getting the product handle for use on the FRONTEND

If your programatically setting a JSON metafield also consider setting up product-reference type metafields, or a metafield list of references then through that get the products.

 

If you must get products by id for the FRONTEND you can try workarounds to do it by the ajax/storefront apis.

https://community.shopify.com/c/technical-q-a/retrieving-multiple-products-by-id-using-the-ajax-api/... 

Other workaround the ajax cart can accept variant.ids and through that can get a product handle.

 

Note- perhaps my concern here for server load, efficiency and speed is a mis-qualified unfounded fear?

In other words: can I go above paginate by 1000, lets say paginate by 25,000 ?

 

Should I just 'not worry' about efficiency and speed of a shop?

(So far, this does not seem to slow the template down)

Pagination max are discussed in other topics, ~1000 is a max

https://community.shopify.com/c/shopify-design/paginate-above-1000-products/td-p/930138 

 

In general increasing pagination counts isn't a good idea and is code smell indicating a deeper  design/architecture problem in whatever is being implemented.

This varies wildly and really you have to just have to test it

https://shopify.dev/themes/best-practices/performance 

https://shopify.dev/themes/tools/theme-inspector 

Contact paull.newton+shopifyforum@gmail.com for the solutions you need


Save time & money ,Ask Questions The Smart Way


Problem Solved? ✔Accept and Like solutions to help future merchants

Answers powered by coffee Thank Paul with a Coffee for more answers or donate to eff.org


cfc_webmaster
Explorer
47 0 126

Whatever is generating that JSON and getting shopify-product-ids should be just as capable of getting the product handle for use on the FRONTEND

If your programatically setting a JSON metafield also consider setting up product-reference type metafields, or a metafield list of references then through that get the products.

 


ME - human typing - I am "generating" that JSON array using the vanilla JSON metafield

I see no other way to stuff in the 2 vars circled here using the Shopify "product" selector metafield.

 

cfc_webmaster_0-1666580362696.png

 

The simplest way to present this problem is:

"What's the best way in LIQUID to GET a product by ID"

 

 

###

Your assuming a product id is permanent and cannot be deleted ,  and ignoring that a product may be duplicated getting a new id and a new handle .

Irrelevant.

The product ID's in this case will NEVER change

And if a product is "duplicated" it's not the same product then and should not appear at all in the X/Y cords I have indicated.

 

The fact that product HANDLE changes makes it useless and unreliable in this usage case. Our Handles will be changing based on SEO needs and the way our INVENTORY system works. We use FISHBOWL Inventory with the Shopify Plugin and all of our SEO handles need to change for various reasons after import, future updates and seo related optimization.

 

ERGO: a PRODUCT ID that is unchanging is needed here.

 

It seems to me perhaps my only option here is to somehow merge the JSON metafield with yet another product list metafield and loop through both of those or merge them somehow...

 

it just seems like such a strange problem.

Why make ALL products available by HANDLE within all_products[handle]

- but not make them available by ID in the same object or a new one like all_products_by_ID[id] ?

 

all_products[handle] is essentially a "database" 

But why choose something for a "unique primary key" like HANDLE that can change?

cfc_webmaster
Explorer
47 0 126

Paul, 

Ive carefully examined your reply here, the API, the forums and explored some tests.

If I have interpreted your reply correctly, then the solution I have here in this video:

https://www.screencast.com/t/hzUxFFj1o 

seems to me to be the only way to accomplish the main goal in LIQUID?

 

Let me know what you think...

Thank you for your time.

friendscottn
Shopify Partner
28 3 18

I ran into this same fun issue today. I didn't find a solution unfortunately. I had to do a loop and use the paginate tag on the all product collection. I tried all_products with handles, but that could only output around 20 products before it stops.