<p>I was finally able to piece this together using Brad's explanation of MatrixBlocks parameters and this thread <a href="https://craftcms.stackexchange.com/questions/856/can-i-get-an-entry-by-matrix-block-id">Can I get an entry by Matrix Block ID?</a></p>

<p>Seems <code>merge([block.owner.id])</code> was the piece I was missing to fold the MatrixBlock query back into an entries loop.</p>

<pre><code>{# Find Matrix Blocks with field value #}
{% set blocks = craft.matrixBlocks.type('variant').fieldId(33).salePrice(':notempty:').all() %}

{# Get entry IDs #}
{% set saleEntryIds = [] %}
{% for block in blocks %}
    {% set saleEntryIds = saleEntryIds|merge([block.owner.id]) %}
{% endfor %}

{# Get entries with limit #}
{% set saleProducts = craft.entries.section('shop').id(saleEntryIds).limit(4) %}

{% for product in saleProducts.all() %}
    {{ product.title }}
    {% for block in product.productVariants.all() %}
        {{ block.salePrice }}
    {% endfor %}
{% endfor %}
</code></pre>

<p>Seems a little overly complicated - maybe there's an easier way to do it?</p>

CC BY-SA 4.0
2024-10-16T13:18:54.133Z
Very handy. Thanks :)
Jonathan Schofield
CC BY-SA 4.0
2019-06-27T14:46:44.547Z
2019-06-27T14:51:49.880Z
2019-06-27T14:51:49.880Z
FortySeven Media
<p>If you have a <code>product</code> entry for each product in your section <code>shop</code>, you could loop and output only the ones that actually have a value in their matrix field <code>salePrice</code> like that:</p>

<ol>
<li>shop = the section that holds your product entries</li>
<li>productVariants = the matrix field handle </li>
<li>variants = the matrix block type that holds the field price value </li>
<li><p>salePrice = the text field that holds the salePrice value</p>

<pre><code> {% set products = craft.entries.section('shop').limit(20) %}
 {% for product in products %}
     {% for block in product.productVariants %}
         {% if block.type == 'variants' and block.salePrice|length %}
             {{ product.url }} - {{ product.title }} - {{ block.salePrice }} &lt;br&gt;
         {% endif %}
     {% endfor %}
 {% endfor %}
</code></pre></li>
</ol>

CC BY-SA 4.0
2019-06-25T14:59:03.553Z
I did that initially, but needed a way to limit the total items on sale, and didn't love that I was literally loading all the products and then showing a few of them. Seemed like there should be a way to filter via a query beforehand.
FortySeven Media
CC BY-SA 4.0
2019-06-25T15:00:51.373Z
You could filter the que by the fields value. Will update the answer according to that.
HendrikEng
CC BY-SA 4.0
2019-06-25T15:33:56.883Z
Yeah that's what I was trying to do, but couldn't find a way to get to the text field inside the matrix field to filter by.
FortySeven Media
CC BY-SA 4.0
2019-06-25T16:44:47.377Z
updated the answer
HendrikEng
CC BY-SA 4.0
2019-06-25T17:01:29.427Z
This is basically the same thing I tried initially. It sort of works, but has a few limitations, thus the reason I was looking for a different way to do it.

These are the issues:
1. I can't set a limit on how many of my sale products to show
2. Because I'm looping through which matrix blocks have content in `salePrice` I can get duplicates of a product if more than one variant are on sale.
FortySeven Media
CC BY-SA 4.0
2019-06-25T17:11:59.967Z
but what are your limitations?
HendrikEng
CC BY-SA 4.0
2019-06-25T17:30:26.450Z
Sorry, it posted prematurely trying to add a new line. 

1. I can't set a limit on how many of my sale products to show 
2. Because I'm looping through which matrix blocks have content in salePrice I can get duplicates of a product if more than one variant are on sale.
FortySeven Media
CC BY-SA 4.0
2019-06-25T20:29:26.567Z
You could set a limit var before looping over the matrix blocks and count it up in the end of each loop, i don't know how you specify if a product has variants, you could use a lightswitch field taht indicates if its for sale or has variants etc. sorry i am not entierly sure how your field setup is ...so i can just make assumptions
HendrikEng
CC BY-SA 4.0
2019-06-24T21:52:52.027Z
2019-06-26T06:54:06.103Z
2019-06-26T06:54:06.103Z
HendrikEng
<p>Not entirely sure how you have things setup, but this is one way.</p>

<p><code>type('prices')</code> will filter down to only block types named <code>prices</code>.</p>

<p><code>fieldId(6)</code> is the ID number of the whole Matrix field.</p>

<p><code>salePrice(':notempty:')</code> will match all fields named <code>salePrices</code> in Matrix blocks that have a value set.</p>

<pre><code>{% set blocks = craft.matrixBlocks.type('prices').fieldId(6).salePrice(':notempty:').all() %}

&lt;ul&gt;
{% for block in blocks %}
    &lt;li&gt;{{ block.salePrice }}&lt;/li&gt;
{% endfor %}
&lt;/ul&gt;
</code></pre>

CC BY-SA 4.0
2019-06-25T23:31:46.863Z
Thanks for the explanation - the types and fieldId make more sense now. For reference:    
`shop` is the main section where the product entries live.  
`productVariants` is a Matrix field where they put in size, price, style, etc...  
`variants` is the block type  
`salePrice` is where they enter a price if applicable.Unfortunately I'm still not quite there. This query only seems to give me back what's  inside the matrix block, I am trying to show the main entry only if the salePrice matrix field has been filled out. How do I use this query in a entires loop to get only the entries I need?
FortySeven Media
CC BY-SA 4.0
2019-06-26T06:50:38.453Z
you would need to loop over the entries in the shop section as well, to output the entries(product) and their urls or title and the price from the matrix...I think you might be overthinking the query, you could simply add a limit when you are fetching the variants from the section and it won't list duplicates since each variant has only one salesPrice.I am not sure if full matrix block query will be more performant than the usual way i posted above....but i might be wrong and @brad-bell will know :) edit: i added the correct handles in the example
HendrikEng
CC BY-SA 4.0
2019-06-26T14:29:47.580Z
Right, I just can't figure out how to use the matrixBlocks query in the loop. I keep thinking I'm over thinking, but if I set the limit on the original loop then it's only looking through 20 of 100 entries and it can't find any on sale. Changing this line and adding a limit does remove duplicates, though `{% for block in product.productVariants.limit(1) %}`
FortySeven Media
CC BY-SA 4.0
2019-06-27T06:11:27.970Z
Hmm, I am wondering why you get duplicates, if each product variant has one matrix field with the salesPrice the query shouldn't result in any duplicates. The query basically just loops over all products and their variants with the salesPrice. Could you post screenshots of your field setup?
HendrikEng
CC BY-SA 4.0
2019-06-27T14:50:29.263Z
Each product has a variant matrix field - that may be the confusion. I ended up finding a way to make the Matrix blocks work - new answer above. Thanks for all your help!
FortySeven Media
CC BY-SA 4.0
2019-06-25T22:01:17.810Z
2019-06-25T22:01:17.810Z
Brad Bell
<p>I have a product with a variant matrix field(<code>productVariants</code>). Inside each variant is the option to supply a sale price (<code>salePrice</code>).</p>

<p>On the front end, I'm trying to show a product grid of only products that are on sale. Sounds simple, but I can't for the life of me figure out the syntax.</p>

<p>Here's where I'm at so far using matrixBlock queries. A few things I am not clear on:</p>

<ol>
<li>owner - what is the owner? Docs only say <code>myEntry</code> and I'm not on a page or in a loop to get the entry that the matrix field is a part of</li>
<li><code>fieldId</code> - is this the matrix field ID or the ID of the text field with the value I'm searching for?</li>
<li>How do I target <code>salePrice</code> in the search syntax since it's one of the fields inside the Matrix field?</li>
</ol>

<pre><code>
{% set myMatrixBlockQuery = craft.matrixBlocks.owner(myEntry).fieldId(33).type('text').search('salePrice:*') %}

{% set saleEntries = myMatrixBlockQuery.all() %}

{% for product in saleEntries %}
{{ product.title }}, etc...
{% endfor %}
</code></pre>

<p>I've spent a couple of hours in StackExchange and in the Craft docs and still can't wrap my head around the syntax for this situation so I appreciate your help!</p>

CC BY-SA 4.0
2019-06-24T21:27:05.613Z
It's a bit confusing if you just added the craft commerce products to a matrix in an entry and want to query over products which are linked in the matrix field e.g. "sale" and display them. Or if you just want to loop over all craft commerce product types that are on sale (what wouldn't require an extra matrix)
HendrikEng
CC BY-SA 4.0
2019-06-25T14:56:23.840Z
I'm not using Craft Commerce - it wasn't in the client's budget so we're doing a combo of Craft, Matrix fields, and a 3rd party processor (SendOwl).
FortySeven Media
<craft3><matrix><queries>
Show Entries based on content in a Matrix Field
# Show Entries based on content in a Matrix Field

(Asked by: username_0 on 2019-06-24)

I have a product with a variant matrix field(productVariants). Inside each variant is the option to supply a sale price (salePrice).
On the front end, I'm trying to show a product grid of only products that are on sale. Sounds simple, but I can't for the life of me figure out the syntax.
Here's where I'm at so far using matrixBlock queries. A few things I am not clear on:

owner - what is the owner? Docs only say myEntry and I'm not on a page or in a loop to get the entry that the matrix field is a part of
fieldId - is this the matrix field ID or the ID of the text field with the value I'm searching for?
How do I target salePrice in the search syntax since it's one of the fields inside the Matrix field?


{% set myMatrixBlockQuery = craft.matrixBlocks.owner(myEntry).fieldId(33).type('text').search('salePrice:*') %}

{% set saleEntries = myMatrixBlockQuery.all() %}

{% for product in saleEntries %}
{{ product.title }}, etc...
{% endfor %}

I've spent a couple of hours in StackExchange and in the Craft docs and still can't wrap my head around the syntax for this situation so I appreciate your help!

**Tags:** craft3, matrix, queries
> **Comments:**
> **username_1**: It's a bit confusing if you just added the craft commerce products to a matrix in an entry and want to query over products which are linked in the matrix field e.g. "sale" and display them. Or if you just want to loop over all craft commerce product types that are on sale (what wouldn't require an extra matrix)  
> **username_0**: I'm not using Craft Commerce - it wasn't in the client's budget so we're doing a combo of Craft, Matrix fields, and a 3rd party processor (SendOwl).  

---

## 3 answers

### Answer by username_0 on 2019-06-27. Score: 4

I was finally able to piece this together using Brad's explanation of MatrixBlocks parameters and this thread Can I get an entry by Matrix Block ID?
Seems merge([block.owner.id]) was the piece I was missing to fold the MatrixBlock query back into an entries loop.
{# Find Matrix Blocks with field value #}
{% set blocks = craft.matrixBlocks.type('variant').fieldId(33).salePrice(':notempty:').all() %}

{# Get entry IDs #}
{% set saleEntryIds = [] %}
{% for block in blocks %}
    {% set saleEntryIds = saleEntryIds|merge([block.owner.id]) %}
{% endfor %}

{# Get entries with limit #}
{% set saleProducts = craft.entries.section('shop').id(saleEntryIds).limit(4) %}

{% for product in saleProducts.all() %}
    {{ product.title }}
    {% for block in product.productVariants.all() %}
        {{ block.salePrice }}
    {% endfor %}
{% endfor %}

Seems a little overly complicated - maybe there's an easier way to do it?

> **Comments:**
> **username_2**: Very handy. Thanks :)  

---

### Answer by username_1 on 2019-06-24. Score: 1

If you have a product entry for each product in your section shop, you could loop and output only the ones that actually have a value in their matrix field salePrice like that:

shop = the section that holds your product entries
productVariants = the matrix field handle 
variants = the matrix block type that holds the field price value 
salePrice = the text field that holds the salePrice value
 {% set products = craft.entries.section('shop').limit(20) %}
 {% for product in products %}
     {% for block in product.productVariants %}
         {% if block.type == 'variants' and block.salePrice|length %}
             {{ product.url }} - {{ product.title }} - {{ block.salePrice }} 
         {% endif %}
     {% endfor %}
 {% endfor %}

> **Comments:**
> **username_0**: I did that initially, but needed a way to limit the total items on sale, and didn't love that I was literally loading all the products and then showing a few of them. Seemed like there should be a way to filter via a query beforehand.  
> **username_1**: You could filter the que by the fields value. Will update the answer according to that.  
> **username_0**: Yeah that's what I was trying to do, but couldn't find a way to get to the text field inside the matrix field to filter by.  
> **username_1**: updated the answer  
> **username_0**: This is basically the same thing I tried initially. It sort of works, but has a few limitations, thus the reason I was looking for a different way to do it.  These are the issues: 1. I can't set a limit on how many of my sale products to show 2. Because I'm looping through which matrix blocks have content in `salePrice` I can get duplicates of a product if more than one variant are on sale.  
> **username_1**: but what are your limitations?  
> **username_0**: Sorry, it posted prematurely trying to add a new line.   1. I can't set a limit on how many of my sale products to show  2. Because I'm looping through which matrix blocks have content in salePrice I can get duplicates of a product if more than one variant are on sale.  
> **username_1**: You could set a limit var before looping over the matrix blocks and count it up in the end of each loop, i don't know how you specify if a product has variants, you could use a lightswitch field taht indicates if its for sale or has variants etc. sorry i am not entierly sure how your field setup is ...so i can just make assumptions  

---

### Answer by username_3 on 2019-06-25. Score: 0

Not entirely sure how you have things setup, but this is one way.
type('prices') will filter down to only block types named prices.
fieldId(6) is the ID number of the whole Matrix field.
salePrice(':notempty:') will match all fields named salePrices in Matrix blocks that have a value set.
{% set blocks = craft.matrixBlocks.type('prices').fieldId(6).salePrice(':notempty:').all() %}


{% for block in blocks %}
    {{ block.salePrice }}
{% endfor %}

> **Comments:**
> **username_0**: Thanks for the explanation - the types and fieldId make more sense now. For reference:     `shop` is the main section where the product entries live.   `productVariants` is a Matrix field where they put in size, price, style, etc...   `variants` is the block type   `salePrice` is where they enter a price if applicable.Unfortunately I'm still not quite there. This query only seems to give me back what's  inside the matrix block, I am trying to show the main entry only if the salePrice matrix field has been filled out. How do I use this query in a entires loop to get only the entries I need?  
> **username_1**: you would need to loop over the entries in the shop section as well, to output the entries(product) and their urls or title and the price from the matrix...I think you might be overthinking the query, you could simply add a limit when you are fetching the variants from the section and it won't list duplicates since each variant has only one salesPrice.I am not sure if full matrix block query will be more performant than the usual way i posted above....but i might be wrong and @brad-bell will know :) edit: i added the correct handles in the example  
> **username_0**: Right, I just can't figure out how to use the matrixBlocks query in the loop. I keep thinking I'm over thinking, but if I set the limit on the original loop then it's only looking through 20 of 100 entries and it can't find any on sale. Changing this line and adding a limit does remove duplicates, though `{% for block in product.productVariants.limit(1) %}`  
> **username_1**: Hmm, I am wondering why you get duplicates, if each product variant has one matrix field with the salesPrice the query shouldn't result in any duplicates. The query basically just loops over all products and their variants with the salesPrice. Could you post screenshots of your field setup?  
> **username_0**: Each product has a variant matrix field - that may be the confusion. I ended up finding a way to make the Matrix blocks work - new answer above. Thanks for all your help!  

---

