Group results by year in labelled sections

Hi, I’m new to Algolia and have been experimenting with it on my Hugo static site.

Currently I have posts grouped by year. e.g.

Is it possible to achieve this same format via instantsearch.js?

So far I’ve only been able to work out how to show a list of posts:

How would I go about grouping/templating the results in to labelled sections (by year from the index)?

Thank you.

What you can do is set attributeForDistinct to year; and then set distinct: 3 (for example, any number could make sense) in your frontend implementation. Then the results will be grouped by year in the response, and you can use _distinctSeqId in the response to show the year.

An example of this is the SaaS use case in the interactive tutorial: https://www.algolia.com/doc/onboarding/#/pick-dataset

@haroen Thank you for this. I’ve managed to set both the attributeForDistinct to year and configure distinct: 3. I see that that the results are grouped by year in the response.

But I’m struggling on just how to configure the frontend hits template to show this. I’m ending up with:

  • 2020
    my post
  • 2020
    another post from 2020
  • 2019
    post from 2019

instead of:

  • 2020
    my post
    another post from 2020
  • 2019
    post from 2019

Could you maybe clarify how do I’d utilise _distinctSeqId in a template so the results are grouped under each year?

my index is rather simple:

{
  "title": "Blackberry and blueberry pie",
  "description": "A delicious pie recipe that combines blueberries and blackberries.",
  "year": 2020
  ...
}

Hi,

I believe you can use the connector connectHits instead of the regular <Hits /> component. This will allow you to have full control on the set of results that are returned, and you could easily do the grouping in the front end by year.

import { connectHits } from 'react-instantsearch-dom';

const GroupedByYearHits = ({ group }) => ... // up to you to design the component however you like

const HitsWithGroups = ({ hits }) => {
  const groups = partitionByYear(hits) // up to you
  return <>
    {groups.map(group => <GroupedByYearHits group={group}/>}
  </>
}

const CustomHits = connectHits(HitsWithGroups) // use this instead of the Hits component in your search template

You can learn more about connectHits in the documentation: Hits | React InstantSearch | API parameters | API Reference | Algolia Documentation

Hope that helps!

2 Likes

grouping could be lodash’ groupBy, or a solution like this:

function distinctResults(results, attributeForDistinct) {
  return results.reduce((acc, curr) => {
    // each result will have a distinct sequence id
    // if it is 0, it means we start a new category
    if (curr._distinctSeqID === 0) {
      // a category is defined by the attribute used for distinct
      acc.push({
        distinctAttribute: curr[attributeForDistinct],
        // and will have an array of results to be able to loop over
        results: [curr]
      });
    } else {
      // if it's not the first distinct sequence, we need to add it to the last results
      acc[acc.length - 1].results.push(curr);
    }
    return acc;
  }, []);
}
1 Like

@haroen & @jonathan.montane Thank you both. I was able to build the hits template with your help.

1 Like