Answers.Body: <p>Yeah you are probably better off putting the startDate, endDate, and price in non matrix fields.  But if you don't something like this should probably work:</p>
  
  <pre><code>{# Get your list of entries (you probably don't want to start with all  entries, this is just an example #}
  {% for entry in entries %}
      {# get the matrix field you want to sort things with #}
      {% for block in entry.yourTravelMatrix %}
          {# get the matrix block by type #}
          {% if block.type == "startDateBlock" %}
              {# set a variable to be the date in the field  #}
              {% set startDateVariable = block.startDateField %}
              {# use the variable to filter the entries #}
              {% if startDateVariable &gt;= (now | date_modify("+1 months") %}
                  {# whatever data you want to show from the entries #}
                  {{ entry.title }}
              {% endif %}
          {% endif %}
      {% endfor %}
  {% endfor %}
  </code></pre>
  
  <p>You'll probably have to adjust it a bit since dateTime fields are different than plain text fields.  There may be a better way to filter by a Matrix field.  Filtering by fields that aren't in a matrix is a lot easier.  This should basically work though.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-04-09T04:47:38.993Z
Answers.Text: Thanks @jason. We share the thought. However there's a small issue with this approach. I cannot paginate the result set, which is quite long.
Answers.UserDisplayName: thoaionline
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-04-08T13:26:24.033Z
Answers.LastActivityDate: 2015-04-08T13:45:56.667Z
Answers.LastEditDate: 2015-04-08T13:45:56.667Z
Answers.UserDisplayName: Jason
Answers.Body: <p>I would like to propose something similar to this as a potential solution:</p>
  
  <pre><code>{# Matrix Search - Reasonably Elegant Solution #}
  
  {# Initialise Matrix Block Owner IDs array #}
  {% set matrixBlockOwnerIds = [] %}
  
  {# This seems to be the easiest way to get the criteria in the shortest route #}
  {% set ecm = craft.entries.section('mySectionHandle').type('myEntryTypeHandle').first().someMatrixBlockTypeHandle %}
  
  {# Reset the owner ID because it was set by the first search #}
  {% do ecm.setAttribute('ownerId', NULL) %}
  
  {# Up the limit for a test - can be removed #}
  {% do ecm.setAttribute('limit', 1000) %}
  
  {# Set some search criteria #}
  {% do ecm.setAttribute('startDate', '&gt;= 2015-06-01') %}
  {% do ecm.setAttribute('endDate', '&lt;= 2015-07-01') %}
  
  {# Find matching blocks #}
  {% set matrixBlocks = ecm.find() %}
  
  {# Iterate blocks and extract owner IDs (entry IDs) #}
  {% for block in matrixBlocks %}
      {% set matrixBlockOwnerIds = matrixBlockOwnerIds|merge([block.ownerId]) %}
  {% endfor %}
  
  {# Query the entries by ID #}
  {% set entries = craft.entries.find({'id': matrixBlockOwnerIds}) %}
  
  {# Iterate entries #}
  {% for entry in entries %}
      &lt;h2&gt;{{ entry.title }}&lt;/h2&gt;
      {# Unfortunately we need to get the matrix blocks again, but this will include all blocks for the entry of that type #}
      {% for block in entry.someMatrixBlockTypeHandle.find() %}
          {# Output some block values #}
          &lt;p&gt;{{ block.valueA }} - {{ block.valueB }}&lt;/p&gt;
      {% endfor %}
  {% endfor %}
  </code></pre>
  
  <p>This isn't exact to your needs but I'm pretty sure it can be adjusted.</p>
  
  <p>You can also do this for numeric ranges: </p>
  
  <pre><code>{% do ecm.setAttribute('someNumericValue', ['and', '&gt; 10', '&lt; 20') %}
  </code></pre>
  
  <p>If you need to combine AND and OR for the same field you'd have to repeat the search with the 'and' set to or, but not reset the matrixBlockOwnerIds array ..</p>
  
  <p>e.g.</p>
  
  <pre><code>{% do ecm.setAttribute('someNumericValue', ['and', '&gt; 10', '&lt; 20') %}
  
  {% set matrixBlocks = ecm.find() %}
  
  {% for block in matrixBlocks %}
      {% set matrixBlockOwnerIds = matrixBlockOwnerIds|merge([block.ownerId]) %}
  {% endfor %}
  
  {% do ecm.setAttribute('someNumericValue', ['and', '&gt; 10', '&lt; 20') %}
  
  {% set matrixBlocks = ecm.find() %}
  
  {% for block in matrixBlocks %}
      {% set matrixBlockOwnerIds = matrixBlockOwnerIds|merge([block.ownerId]) %}
  {% endfor %}
  </code></pre>
  
  <p>If you need any help with these examples, just give me a message.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-06-09T17:09:42.933Z
Answers.LastActivityDate: 2015-06-09T17:09:42.933Z
Answers.UserDisplayName: Jay
Answers.Body: <p>What I've done in a comparable situation is to add a hidden field to that entry type. And then I save Matrix data to that field on every save by listening to <a href="http://buildwithcraft.com/docs/plugins/events-reference#entries-onBeforeSaveEntry" rel="nofollow"><code>onBeforeSaveEntry</code></a> events.</p>
  
  <p>This makes the access to such processed Matrix data in templates or other parts of your plugin (i.e. <a href="http://buildwithcraft.com/docs/plugins/hooks-reference#getEntryTableAttributeHtml" rel="nofollow"><code>getEntryTableAttributeHtml</code></a>) very easy.</p>
  
  <p><strong>Event handler</strong></p>
  
  <pre><code>craft()-&gt;on('entries.onBeforeSaveEntry', function(Event $event)
  {
      $entry = $event-&gt;params['entry'];
  
      if($entry-&gt;section['handle'] == 'campaigns')
      {
          $longTravels = false;
  
          foreach ($entry-&gt;travelDates as $travelDate)
          {
              $duration = $travelDate-&gt;startDate-&gt;diff($travelDate-&gt;endDate);
  
              if ($duration &gt; new DateInterval('P30D') &amp;&amp; $duration &lt; new DateInterval('P60D'))
              {
                  $longTravels = true;
                  break;
              }
          }
  
          // Set value for hidden field 'longTravels'
          $entry-&gt;getContent()-&gt;longTravels = $longTravels;
      }
  });
  </code></pre>
  
  <p><strong>CSS for hidden field type</strong></p>
  
  <pre><code>{% set hiddenField %}
      #fields-{{ id }}-field {
          display: none;
      }
  {% endset %}
  
  {% includeCss hiddenField %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-08-22T12:46:20.870Z
Answers.Text: Along this route, you also might want to check out the [Preparse Field](https://github.com/aelvan/Preparse-Field-Craft) plugin – it sure helped me fetch the relevant data that was stored within a matrix.
Answers.UserDisplayName: Avant la lettre
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-08-23T06:27:06.523Z
Answers.Text: @Avantlalettre good suggestion, I think I wrote this answer before the Preparse plugin existed. Today, I use Preparse a lot for these kind of things. You might want to post your comment as a separate answer though, it’s a bit burried in all this text and code. I’d definitly upvote it (and accept, if it was my decision :D).
Answers.UserDisplayName: carlcs
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-04-08T15:17:22.500Z
Answers.LastActivityDate: 2015-04-08T15:28:39.410Z
Answers.LastEditDate: 2015-04-08T15:28:39.410Z
Answers.UserDisplayName: carlcs
Body: <p>I'm building a travel site containing Campaigns (entries)</p>
  
  <p>Each of these campaigns has multiple travel dates, modelled by a matrix field of</p>
  
  <p>[startDate, endDate, price]</p>
  
  <p>I want to do the following searches:</p>
  
  <ul>
  <li>Campaigns with a travel startDate next month</li>
  <li>Campaigns whose duration is more than 30 days and less than 60 days (endDate-startDate)</li>
  <li>One of those criteria</li>
  <li>All of the above criteria</li>
  </ul>
  
  <p>How can this be achieved with twig template or custom controller?</p>
  
  <p>PS: I looked into <a href="http://buildwithcraft.com/docs/relations" rel="noreferrer">relations</a> but that only applies to <code>entries</code> field, not matrix, and neither does it allow filtering on the related entity.</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2015-04-08T12:48:45.143Z
Comments.Text: I'd seriously question the use of a matrix field for that sort of data - sounds like all of those values will be required for each entry and moving them to their own fields would make those searches a lot simpler.
Comments.UserDisplayName: Adam Gilleard
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2015-04-08T13:39:29.487Z
Comments.Text: @Adam you're right, it is a lot simpler to filter entries by direct fields, but this shouldn't be a reason to decide against Matrix. You probably missed that the OP mentioned that each of these entries "campaigns" got multiple (maybe even optional) Matrix blocks "Travel dates".
Comments.UserDisplayName: carlcs
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2015-04-08T14:22:00.107Z
Comments.Text: @carlcs you're right, I had missed the potential for multiple dates - apologies
Comments.UserDisplayName: Adam Gilleard
Tags: <matrix><field><search>
Title: Search for entries with matrix field's value
ThreadText: # Search for entries with matrix field's value
  
  (Asked by: username_0 on 2015-04-08)
  
  I'm building a travel site containing Campaigns (entries)
  
  Each of these campaigns has multiple travel dates, modelled by a matrix field of
  
  [startDate, endDate, price]
  
  I want to do the following searches:
  
  * Campaigns with a travel startDate next month
  * Campaigns whose duration is more than 30 days and less than 60 days (endDate-startDate)
  * One of those criteria
  * All of the above criteria
  
  How can this be achieved with twig template or custom controller?
  
  PS: I looked into [relations](http://buildwithcraft.com/docs/relations) but that only applies to `entries` field, not matrix, and neither does it allow filtering on the related entity.
  
  **Tags:** matrix, field, search
  
  > **Comments:**
  > **username_1**: I'd seriously question the use of a matrix field for that sort of data - sounds like all of those values will be required for each entry and moving them to their own fields would make those searches a lot simpler.  
  > **username_2**: @username_1 you're right, it is a lot simpler to filter entries by direct fields, but this shouldn't be a reason to decide against Matrix. You probably missed that the OP mentioned that each of these entries "campaigns" got multiple (maybe even optional) Matrix blocks "Travel dates".  
  > **username_1**: @username_2 you're right, I had missed the potential for multiple dates - apologies  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_2 on 2015-04-08. Score: 4 | Accepted answer
  
  What I've done in a comparable situation is to add a hidden field to that entry type. And then I save Matrix data to that field on every save by listening to [`onBeforeSaveEntry`](http://buildwithcraft.com/docs/plugins/events-reference#entries-onBeforeSaveEntry) events.
  
  This makes the access to such processed Matrix data in templates or other parts of your plugin (i.e. [`getEntryTableAttributeHtml`](http://buildwithcraft.com/docs/plugins/hooks-reference#getEntryTableAttributeHtml)) very easy.
  
  **Event handler**
  
  ```
  craft()->on('entries.onBeforeSaveEntry', function(Event $event)
  {
      $entry = $event->params['entry'];
  
      if($entry->section['handle'] == 'campaigns')
      {
          $longTravels = false;
  
          foreach ($entry->travelDates as $travelDate)
          {
              $duration = $travelDate->startDate->diff($travelDate->endDate);
  
              if ($duration > new DateInterval('P30D') && $duration < new DateInterval('P60D'))
              {
                  $longTravels = true;
                  break;
              }
          }
  
          // Set value for hidden field 'longTravels'
          $entry->getContent()->longTravels = $longTravels;
      }
  });
  
  ```
  
  **CSS for hidden field type**
  
  ```
  {% set hiddenField %}
      #fields-{{ id }}-field {
          display: none;
      }
  {% endset %}
  
  {% includeCss hiddenField %}
  
  ```
  
  > **Comments:**
  > **username_5**: Along this route, you also might want to check out the [Preparse Field](https://github.com/aelvan/Preparse-Field-Craft) plugin – it sure helped me fetch the relevant data that was stored within a matrix.  
  > **username_2**: @username_5 good suggestion, I think I wrote this answer before the Preparse plugin existed. Today, I use Preparse a lot for these kind of things. You might want to post your comment as a separate answer though, it’s a bit burried in all this text and code. I’d definitly upvote it (and accept, if it was my decision :D).  
  
  ---
  
  ### Answer by username_3 on 2015-04-08. Score: 2
  
  Yeah you are probably better off putting the startDate, endDate, and price in non matrix fields. But if you don't something like this should probably work:
  
  ```
  {# Get your list of entries (you probably don't want to start with all  entries, this is just an example #}
  {% for entry in entries %}
      {# get the matrix field you want to sort things with #}
      {% for block in entry.yourTravelMatrix %}
          {# get the matrix block by type #}
          {% if block.type == "startDateBlock" %}
              {# set a variable to be the date in the field  #}
              {% set startDateVariable = block.startDateField %}
              {# use the variable to filter the entries #}
              {% if startDateVariable >= (now | date_modify("+1 months") %}
                  {# whatever data you want to show from the entries #}
                  {{ entry.title }}
              {% endif %}
          {% endif %}
      {% endfor %}
  {% endfor %}
  
  ```
  
  You'll probably have to adjust it a bit since dateTime fields are different than plain text fields. There may be a better way to filter by a Matrix field. Filtering by fields that aren't in a matrix is a lot easier. This should basically work though.
  
  > **Comments:**
  > **username_0**: Thanks @username_3. We share the thought. However there's a small issue with this approach. I cannot paginate the result set, which is quite long.  
  
  ---
  
  ### Answer by username_4 on 2015-06-09. Score: 1
  
  I would like to propose something similar to this as a potential solution:
  
  ```
  {# Matrix Search - Reasonably Elegant Solution #}
  
  {# Initialise Matrix Block Owner IDs array #}
  {% set matrixBlockOwnerIds = [] %}
  
  {# This seems to be the easiest way to get the criteria in the shortest route #}
  {% set ecm = craft.entries.section('mySectionHandle').type('myEntryTypeHandle').first().someMatrixBlockTypeHandle %}
  
  {# Reset the owner ID because it was set by the first search #}
  {% do ecm.setAttribute('ownerId', NULL) %}
  
  {# Up the limit for a test - can be removed #}
  {% do ecm.setAttribute('limit', 1000) %}
  
  {# Set some search criteria #}
  {% do ecm.setAttribute('startDate', '>= 2015-06-01') %}
  {% do ecm.setAttribute('endDate', '<= 2015-07-01') %}
  
  {# Find matching blocks #}
  {% set matrixBlocks = ecm.find() %}
  
  {# Iterate blocks and extract owner IDs (entry IDs) #}
  {% for block in matrixBlocks %}
      {% set matrixBlockOwnerIds = matrixBlockOwnerIds|merge([block.ownerId]) %}
  {% endfor %}
  
  {# Query the entries by ID #}
  {% set entries = craft.entries.find({'id': matrixBlockOwnerIds}) %}
  
  {# Iterate entries #}
  {% for entry in entries %}
      <h2>{{ entry.title }}</h2>
      {# Unfortunately we need to get the matrix blocks again, but this will include all blocks for the entry of that type #}
      {% for block in entry.someMatrixBlockTypeHandle.find() %}
          {# Output some block values #}
          <p>{{ block.valueA }} - {{ block.valueB }}</p>
      {% endfor %}
  {% endfor %}
  
  ```
  
  This isn't exact to your needs but I'm pretty sure it can be adjusted.
  
  You can also do this for numeric ranges:
  
  ```
  {% do ecm.setAttribute('someNumericValue', ['and', '> 10', '< 20') %}
  
  ```
  
  If you need to combine AND and OR for the same field you'd have to repeat the search with the 'and' set to or, but not reset the matrixBlockOwnerIds array ..
  
  e.g.
  
  ```
  {% do ecm.setAttribute('someNumericValue', ['and', '> 10', '< 20') %}
  
  {% set matrixBlocks = ecm.find() %}
  
  {% for block in matrixBlocks %}
      {% set matrixBlockOwnerIds = matrixBlockOwnerIds|merge([block.ownerId]) %}
  {% endfor %}
  
  {% do ecm.setAttribute('someNumericValue', ['and', '> 10', '< 20') %}
  
  {% set matrixBlocks = ecm.find() %}
  
  {% for block in matrixBlocks %}
      {% set matrixBlockOwnerIds = matrixBlockOwnerIds|merge([block.ownerId]) %}
  {% endfor %}
  
  ```
  
  If you need any help with these examples, just give me a message.
  
  
  ---
  
  