Solved

How can I filter collections by metafields in liquid?

maxwkf
Shopify Partner
16 1 0

Hi there,

 

I would like to do filtering of my collections by metafields in liquid. How should I do it?

 

If I use the where in collection predefined fields, I can do it like this. {% assign collections = collections | where: 'description', 'promotion' %}

 

But while I am trying to do query on the 'group' metafield I have created, it simply not working.

 

{% assign collections = collections | where: 'metafields.custom.group', 'promotion' %}

 

I tried to use this solution (https://community.shopify.com/c/technical-q-a/filtering-collections-by-metafields-using-where/m-p/18...) and surf on the Internet and can get no useful information.

 

Please help Thanks

Accepted Solution (1)

maxwkf
Shopify Partner
16 1 0

This is an accepted solution.

I think the where in liquid won't be able to support a dot operator to retrieve nested array value.

The following is the definition of where in ruby.  Unless array in Ruby support dot operator property value like 'metafields.custom.group', it cannot support for what I mentioned.

# @liquid_public_docs
    # @liquid_type filter
    # @liquid_category array
    # @liquid_summary
    #   Filters an array to include only items with a specific property value.
    # @liquid_description
    #   This requires you to provide both the property name and the associated value.
    # @liquid_syntax array | where: string, string
    # @liquid_return [array[untyped]]
    def where(input, property, target_value = nil)
      ary = InputIterator.new(input, context)

      if ary.empty?
        []
      elsif target_value.nil?
        ary.select do |item|
          item[property]
        rescue TypeError
          raise_property_error(property)
        rescue NoMethodError
          return nil unless item.respond_to?(:[])
          raise
        end
      else
        ary.select do |item|
          item[property] == target_value
        rescue TypeError
          raise_property_error(property)
        rescue NoMethodError
          return nil unless item.respond_to?(:[])
          raise
        end
      end
    end

 

View solution in original post

Replies 3 (3)

NomtechSolution
Astronaut
1245 113 149

To filter collections by metafields in Liquid, you can use the following approach:

  1. Retrieve all collections using the collections object. For example: {% assign collections = collections.all %}.
  2. Loop through the collections and filter them based on the desired metafield value. In this case, the metafields.custom.group metafield is used for filtering.
  3. Use the where filter to compare the metafield value and filter the collections accordingly.

Here's an example of how you can achieve this:

{% assign filteredCollections = collections.all | where: 'metafields.custom.group', 'promotion' %}

{% for collection in filteredCollections %}
  <h2>{{ collection.title }}</h2>
  <!-- Display other collection information here -->
{% endfor %}

In this example, the filteredCollections variable will contain only the collections that have a metafield with the key custom and value promotion in the group subfield.

maxwkf
Shopify Partner
16 1 0

{{ collections.all }} returns a null

maxwkf
Shopify Partner
16 1 0

This is an accepted solution.

I think the where in liquid won't be able to support a dot operator to retrieve nested array value.

The following is the definition of where in ruby.  Unless array in Ruby support dot operator property value like 'metafields.custom.group', it cannot support for what I mentioned.

# @liquid_public_docs
    # @liquid_type filter
    # @liquid_category array
    # @liquid_summary
    #   Filters an array to include only items with a specific property value.
    # @liquid_description
    #   This requires you to provide both the property name and the associated value.
    # @liquid_syntax array | where: string, string
    # @liquid_return [array[untyped]]
    def where(input, property, target_value = nil)
      ary = InputIterator.new(input, context)

      if ary.empty?
        []
      elsif target_value.nil?
        ary.select do |item|
          item[property]
        rescue TypeError
          raise_property_error(property)
        rescue NoMethodError
          return nil unless item.respond_to?(:[])
          raise
        end
      else
        ary.select do |item|
          item[property] == target_value
        rescue TypeError
          raise_property_error(property)
        rescue NoMethodError
          return nil unless item.respond_to?(:[])
          raise
        end
      end
    end