Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-10-16T13:18:54.133Z
Answers.Text: Very handy. Thanks :)
Answers.UserDisplayName: Jonathan Schofield
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-27T14:46:44.547Z
Answers.LastActivityDate: 2019-06-27T14:51:49.880Z
Answers.LastEditDate: 2019-06-27T14:51:49.880Z
Answers.UserDisplayName: FortySeven Media
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T14:59:03.553Z
Answers.Text: 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.
Answers.UserDisplayName: FortySeven Media
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T15:00:51.373Z
Answers.Text: You could filter the que by the fields value. Will update the answer according to that.
Answers.UserDisplayName: HendrikEng
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T15:33:56.883Z
Answers.Text: 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.
Answers.UserDisplayName: FortySeven Media
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T16:44:47.377Z
Answers.Text: updated the answer
Answers.UserDisplayName: HendrikEng
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T17:01:29.427Z
Answers.Text: 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.
Answers.UserDisplayName: FortySeven Media
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T17:11:59.967Z
Answers.Text: but what are your limitations?
Answers.UserDisplayName: HendrikEng
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T17:30:26.450Z
Answers.Text: 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.
Answers.UserDisplayName: FortySeven Media
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T20:29:26.567Z
Answers.Text: 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
Answers.UserDisplayName: HendrikEng
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-24T21:52:52.027Z
Answers.LastActivityDate: 2019-06-26T06:54:06.103Z
Answers.LastEditDate: 2019-06-26T06:54:06.103Z
Answers.UserDisplayName: HendrikEng
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T23:31:46.863Z
Answers.Text: 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?
Answers.UserDisplayName: FortySeven Media
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-26T06:50:38.453Z
Answers.Text: 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
Answers.UserDisplayName: HendrikEng
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-26T14:29:47.580Z
Answers.Text: 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) %}`
Answers.UserDisplayName: FortySeven Media
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-27T06:11:27.970Z
Answers.Text: 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?
Answers.UserDisplayName: HendrikEng
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-27T14:50:29.263Z
Answers.Text: 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!
Answers.UserDisplayName: FortySeven Media
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-25T22:01:17.810Z
Answers.LastActivityDate: 2019-06-25T22:01:17.810Z
Answers.UserDisplayName: Brad Bell
Body: <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>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-06-24T21:27:05.613Z
Comments.Text: 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)
Comments.UserDisplayName: HendrikEng
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-06-25T14:56:23.840Z
Comments.Text: 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).
Comments.UserDisplayName: FortySeven Media
Tags: <craft3><matrix><queries>
Title: Show Entries based on content in a Matrix Field
ThreadText: # 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:
  
  1. 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
  2. `fieldId` - is this the matrix field ID or the ID of the text field with the value I'm searching for?
  3. 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 username_3's explanation of MatrixBlocks parameters and this thread [Can I get an entry by Matrix Block ID?](https://craftcms.stackexchange.com/questions/856/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:
  
  1. shop = the section that holds your product entries
  2. productVariants = the matrix field handle
  3. variants = the matrix block type that holds the field price value
  4. 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 }} <br>
              {% 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() %}
  
  <ul>
  {% for block in blocks %}
      <li>{{ block.salePrice }}</li>
  {% endfor %}
  </ul>
  
  ```
  
  > **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 @username_3 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!  
  
  ---
  
  