Is it possible to display an entry field in search results if it contains the search query?

Context: I have an entry with a list of PDF assets. I want to show an asset in the search results if it contains the search query in the asset title. By default all the asset titles would display if any one contains the search query.

This is what I have in mind:

{% set searchQuery = craft.app.request.getParam('q') %}
{% set entries = craft.entries
  'and', 'resources'
  .all() %}
{% if entries|length %}
  {% for entry in entries %}
  <li><a href="{{ entry.url }}">{{ entry.title }}</a><br>
          {% set block = entry.downloads.all() %}   
          {% if block|length %}
                {% for file in block %}
                  {% for asset in file.file.all() %}
                  {% if asset ***CONTAINS SEARCHQUERY*** %}
                      {{ asset.title }}
                  {% endif %}   
                  {% endfor %}<br>
                {% endfor %}
          {% endif %}   
  {% endfor %}
{% endif %}
New contributor
Andrew is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

Like all relational fields, Assets fields return an ElementQuery instance (element queries are basically pre-baked query builders for fetching elements). You can use that ElementQuery's title() parameter to narrow down results based on assets' titles, including fuzzy searching. Here's how you could query for only assets with a title that contains the search query:

{% for asset in file.file.title('*' ~ searchQuery  ~ '*').all() %}
    {{ asset.title }}
{% endfor %}

Basically, the above appends * before and after the search query, which tells the ElementQuery returned by the Assets field (file.file, in your case) to only query for assets with titles that contain the search query somewhere.

There are other possible syntaxes available as well, depending on how you want to approach the title matching – see the official docs for more info.

  • This works perfectly for the example above. But I've tried to use the same code for a different Matrix block and I'm struggling to get it to work. The Matrix field is similar, but uses a different handle. The block handle is 'file' and the field handle is 'fileTitle', so I'm assuming it should be: {% for asset in file.fileTitle.title('' ~ searchQuery ~ '').all() %} {{ asset.title }} {% endfor %} - this doesn't work, so any help greatly appreciated!
    – Andrew
    Jan 14 at 10:46
  • You’re missing the asterisks before and after the searchQuery, unless that was just a typo in your comment. Without the asterisks, Craft will query for assets with a filetitle exactly equal to the search query, which I assume is not what you want. Jan 14 at 18:35
  • My mistake, the second version is a Matrix block with a text field. So I need the search query for a text field not an asset field. Unfortunately I cannot find any information on this anywhere. Once again any help would be fantastic!
    – Andrew
    9 hours ago
  • @Andrew If file.fileTitle is a plain text field, you should be able to simply do file.fileTitle('*' ~ searchQuery ~ '*') instead. 5 hours ago

Your Answer

Andrew is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.