Sorting 'related items' by multiple facets

(Apologies for the somewhat broad title)

Use case

I’d like to be able to determine related posts based off multiple category names.

Setup

Sample data below, with categories.name marked for faceting.

All other index settings are unchanged and ranking is left as default.

{
  "categories": [
    { "name": "Art" },
    { "name": "Science" },
    { "name": "Theatre" }    
  ],
  "title": "bar",
},
{
  "categories": [
    { "name": "Science" }
  ],
  "title": "qux"
},
{
  "categories": [
    { "name": "Art" }
  ],
  "title": "baz",
},
{
  "categories": [
    { "name": "Art" },
    { "name": "Athletics" },
    { "name": "Science" }
  ],
  "title": "foo",
},

The following query (in the Dashboard) returns posts that have either art OR science categories as expected.

My understanding is that with the below query, a post with both category names will be treated as a single matching filter.

{
  "facetFilters": [
    ["categories.name:Art", "categories.name:Science"]
  ]
}

OR

{
  "filters": "categories.name:Art OR categories.name:Science"
}

However, I’d like the results from the above query to be sorted by posts that include both categories first.

E.g.

{
  "categories": [
    { "name": "Art" },
    { "name": "Athletics" },
    { "name": "Science" }
  ],
  "title": "foo",
},
{
  "categories": [
    { "name": "Art" },
    { "name": "Science" },
    { "name": "Theatre" }    
  ],
  "title": "bar",
},
{
  "categories": [
    { "name": "Art" }
  ],
  "title": "baz",
},
{
  "categories": [
    { "name": "Science" }
  ],
  "title": "qux"
},

What would be the idiomatic way to achieve this with Algolia? Does the answer lie in denormalising this data set?

Any advice much appreciated!

Hi @robin.pyon,

Thanks for contacting Algolia!

What you are looking for is sumOrFiltersScores which will add together the scores of your disjunctive filters.

When using filters, a “score” is applied to each matching filter and the default score is 1. For example, with your sample filter, the engine reads your filter like this:

"filters": "(categories.name:Art<score=1> OR categories.name:Science<score=1>)"

In a disjunctive “OR” filter, such as in your example, we only need to match one category to be a relevant result. Therefore, all results that match end up with a score of 1 and are deemed “equal” - this is why they end up in the order where matching one category might end up before or in between results matching two categories.

To achieve your desired result where results with both categories are first just set sumOrFiltersScores to true:

{ 
    "filters": "categories.name:Art OR categories.name:Science", 
    "sumOrFiltersScores": true 
}

Here is a GIF of the query param working in the Algolia dashboard:

46

Hope this helps!

1 Like

Hi Ajay,

Thanks for the speedy reply – sumOrFiltersScore: true did the trick.

Much appreciated!

1 Like