'Liquid - How to create a list of products filtered by metafield

I am trying to create a list of products that have been filtered by their respective metafields.

If I could pass nested properties to the where filter (it appears this is not possible), this would be perfect:

{% assign products = collection.products | where: "metafields.my_fields.product_in_stock", "1" %}

However, as it does not seem possible to pass nested properties to the where filter, is there an alternative approach to building this filtered array?

I have tried multiple version of creating a variable, and trying to assign products to that variable to no success yet.

Our use case is: We have thousands of products. Thousands of them are out of stock at any one time. I would like to have the pages indexable by search engines, without having to remove the pages from the site, and without thousands of out of stock products clogging up our collections.

In summary: I would like to be able to display some out of stock products, but not all of them.

Any help would be hugely appreciated!

Why not use the following code:

{% for product in products %}
  {% if product.metafields.my_fields.product_in_stock == 1 %}
    <do processing>
  {% else %}
    {% continue %}
  {% endif %}
{% endfor %}

Because looping is limited to 50 per page as specified here. Thus, if only 46 of the 50 loops pass the if condition, only 46 products will be displayed on the page (as the loop will stop executing once it gets to 50 iterations). I would like to have control over the number of items on the page - so this approach is not feasible.

That said, you can overcome the 50 iteration limit by setting pagination to a higher value. The Shopify documentation states that the pagination object is limited to 50 but this is not correct (as of 17th March 2022) as this limit is actually 1000 (see SO discussion about this here); however this approach introduces two other problems:

  1. It is unsupported functionality so it is unclear when/if this would ever change (Shopify documentation specifies that pagination should be limited to 50)
  2. The pagination object would now be using 1000, thus paginating through results would need to be handled via a separate control mechanism.

Example of this approach here:

{% paginate collection.products by 1000 %}
  {% assign counter = 0 %}
  {% for product in collection.products %}
    {% if counter < 50 AND product.metafields.my_fields.product_in_stock == 1 %}
      {% assign counter = counter + 1 %}
      <do processing>
    {% else %}
      {% continue %}
    {% endif %}
  {% endfor %}
{% endpaginate %}

The above code will allow you to always display 50 products per page, however, if you use anything related to the paginate object - you will access the wrong results - as the paginate object will be paginating by 1000, when you are only displaying 50 results per page.

Thus, I would like to find out if there is a way to achieve the outlined functionality in liquid (without going headless! If I go headless there are a million ways I can achieve the functionality I outline above).

Specifically: how to reliably display a list of 50 products that match a metafield critera?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source