5

I am using Algolia instantsearch.js to display candidates to an election (here: https://laprimaire.org/candidats/). I would like the initial display of candidates to be random so that every candidate gets more or less the same visibility.

I read in this answer that it is not a feature of Algolia but that it should be possible to do it anyway with a little js trick : Is it possible to sort randomly, and to query on field if it exists?

Problem is I am using instantsearch.js and I cannot find how to implement the above searchFunction in the case of instantsearch.js.

I see from the documentation that instantsearch can be initialized with a searchFunction which receives a helper as a parameter: https://community.algolia.com/instantsearch.js/documentation/#initialization

However it did not find documentation about this helper and how to manipulate it, so that I can apply the random function to the search results.

Any help would be greatly appreciated ! Thanks a lot

Thibauld

Community
  • 1
  • 1
Thibauld
  • 183
  • 1
  • 9
  • Just a little clarification here, in the answer to [Is it possible to sort randomly, and to query on field if it exists?](http://stackoverflow.com/questions/33123488/is-it-possible-to-sort-randomly-and-to-query-on-field-if-it-exists) , the JS involved will just mix together results on the same page. Hence if your result list is paginated, I'm not sure this will achieve what you're looking for. – Jerska Apr 20 '16 at 15:43
  • After seeing your webpage, it doesn't seem like an issue though. – Jerska Apr 20 '16 at 15:52

1 Answers1

4

The hits widget has a way for you to get more control on how to display the list of hits through the transformData.allItems and templates.allItems parameters.

Using the shuffle method of this question How can I shuffle an array? :

function shuffle (o){
  for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
  return o;
}

You can simply do:

search.addWidget(
  instantsearch.widgets.hits({
    // Your other options
    transformData: {
      allItems: function (content) {
        return { hits: shuffle(content.hits) };
      }
    },
    templates: {
      empty: 'No results',
      allItems: '{{#hits}}<your previous templates.hit value>{{/hits}}'
    }
  })
);

The {{#hits}}{{/hits}} template is simply some Hogan.js logic to loop on each of your hits.

Community
  • 1
  • 1
Jerska
  • 11,722
  • 4
  • 35
  • 54
  • Great ! Worked like a charm :) Thanks a lot ! – Thibauld Apr 20 '16 at 20:52
  • 1
    Just want to point out that this works for small indices, where all objects can be loaded instantly in one list. If you are implementing pagination on your page, you have to write an updater, that updates a random value of each object (e.g. once per day, every hour ...). Then you can add this value as a ranking attribute. – bobski Mar 18 '20 at 13:34