Search code examples
sortingsolrsunspot

In Solr, how to sort documents differently based on their attributes?


My documents have these 2 fields:

  • status
    • open
    • upcoming
    • ended
  • end_date

Right now I'm sorting this way:

status_int ASC, end_date ASC (status_int is just a way to easily order by status open -> upcoming -> ended)

For open and upcoming events, I want to show the ones that end the soonest first, that's why I have end_date ASC. The issue is that it doesn't work well for ended events, as the user will get the events from 2010 for instance before the ones that ended in 2020.

So, I'd like to order by end_date ASC for documents that dont have the ended status, and end_date DESC for the ended ones.

Is it possible to change the order based on a document attribute?


Solution

  • On top of my head, an easy solution is to use streaming expressions, although the usability of them depends on some technical details (Solr version, your client implementation details etc.)

    Start two search streams, one for documents which don't have the ended status, and one for others. You can specify different sort criterias for two different streams. Then merge those two streams. Something like:

    list(
        search(
            yourCollection,
            q="yourQuery",
            qt="/export", //or "/select" based on your needs
            fq="*:* AND NOT status:ended",
            sort="end_date asc"
        ),
        search(
            yourCollection,
            q="yourQuery",
            qt="/export", //or "/select" based on your needs
            fq="status:ended",
            sort="end_date desc"
        )
    )
    

    this will first return not-ended ones sorted by end_date asc, and after them status=ended ones sorted by end_date desc. You can also sort them again based on some other condition, or merge them differently based on your requirements.


    Another simpler solution could be using function queries and pseudo fields, something along the lines of:

    &fl=sortonthis:if(not(status=ended),rord(end_date),ord(end_date))&sort=sortonthis asc

    I didn't test but it should work with some tweaks.