6

Currently I am sorting a category template with this:

'featured desc, postDate desc'

Works as expected. But I would like to sort it first on the featured field, then on the score. Such as

'featured desc, score'

But this throws an error. Can someone explain why that is and how I might achieve what I'm looking for? The first search is good for bringing featured posts to the top, but if there are none or maybe one, the rest of the results are not all that relevant. Ideas?

Thanks in advance.

1
  • 1
    It would be great if you could post your whole query and also clarify what score and featured are exactly? Custom fields? If so, what type(s)?
    – Jalen Davenport
    Jul 27, 2018 at 19:21

1 Answer 1

10

I assume you're using .search() – a common mistake is to try to combine orderBy('score') with custom fields, which doesn't work because the score attribute isn't an actual field, but a computed value that Craft "injects" into the element model.

If I understand you correctly, you want to render any "featured" entries at the top of the search results. You could achieve this by doing two separate search queries, before merging the results, with the featured entries at the beginning of the entry results array. Assuming featured is a Lightswitch field, something like this should work:

{% set searchQuery = craft.entries.search('foo').orderBy('score') %}
{% set featuredEntries = searchQuery.featured('1').all() %}
{% set notFeaturedEntries = searchQuery.featured('not 1').all() %}

{% set allEntries = featuredEntries|merge(notFeaturedEntries) %}

{% for entry in allEntries %}
    ...
{% endfor %}

If you need to use pagination, the above won't fly – in which case you could opt to just collect the entry IDs and do a third query to pull the full entry models for a paginated result set:

{% set featuredEntryIds = searchQuery.featured('1').ids() %}
{% set notFeaturedEntryIds = searchQuery.featured('not 1').ids() %}
{% set allEntryIds = featuredEntryIds|merge(notFeaturedEntryIds) %}

{% paginate searchQuery.featured(null).limit(10).id(allEntryIds).fixedOrder(true) as pageInfo, pageEntries %}

An alternative approach to the above is to just have a single query, and use the group filter to sort out the featured entries from the non-featured ones:

{% set entries = craft.entries.search('foo').orderBy('score').all()|group('featured') %}
{% set featuredEntries = entries['1'] ?? [] %}
{% set notFeaturedEntries = entries[''] ?? [] %}

Note: If you're using Craft 2, be sure to replace the orderBy parameter with order. Using order in Craft 3 will still work, but the parameter is deprecated and will not work in Craft 4.

2
  • This worked great for pagination and placing 'featured' entries at the top. I did have to edit the paginate tag from searchQuery to craft.entries() to get the correct order.
    – Jeff Irwin
    Nov 10, 2020 at 22:40
  • OMG, tried everything to get a custom pagination to work, finally got it with .fixedOrder(true) thanks!
    – Leoncio
    Nov 6, 2022 at 2:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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