Search results to mimic algolia.com/search

Hi, we want our search to results to mimic the algolia search results page at Search | Algolia - I’m referring to grouping of search results. Our site is a Wordpress site, so the search index is in a few different groups - posts, pages, help, and app. Help and app pages I inserted into the index manually.

Basically, we want the results page to be grouped - see attached image.

It seems as though I need to do something with ‘attributeForDistinct’, but I can’t figure out how to then, say, only show the results for “Pages”, then “Posts”, then “Help”, then “App”. Perhaps something like the solution described here would work:Group results by year in labelled sections - #5 by haroen, but I’m not sure if this applies or not.

Here’s what the index looks like:

“hits”: [
{
“post_id”: 123,
“post_type”: “page”,
“post_type_label”: “Pages”,
“post_title”: “This is an example page”
},
{
“post_id”: 124,
“post_type”: “post”,
“post_type_label”: “Posts”,
“post_title”: “10 ways to do something exciting”
},
{
“post_id”: 127,
“post_type”: “help”,
“post_type_label”: “Help Articles”,
“post_title”: “This is a help page”
},
{
“post_id”: 128,
“post_type”: “website”,
“post_type_label”: “Website”,
“post_title”: “This is api documentations”
}
]

Thanks for any help or guidance with this!

On the Algolia site those are separate indices using our federated search features.

I will have a look if I can make a public version of the code

Thanks! I see what you’ve done here: federated-search-autocomplete-demo - CodeSandbox, and I’m trying to mimic that a bit but it’s not easy. Any php that you can open source or help with would be great!

It’s not made with php, but with react unfortunately, so I can’t share any php.

I’ve tried to extract the search, however the styling seemed to be impossible (sorry!)

Hi @haroen, this has helped, I’ve almost got it working. There’s one bit that’s giving me trouble though, I’m not sure how to implement pagination with federated search. With the search at Search | Algolia, each pagination widget works on each individual section independently - if you go to the second page of the “Website” section searches only those results paginate. How do I implement that with instantsearch.js? My pagination widget currently is moving all widgets on the page to the 2nd page. Here’s the code I have right now:

type or paste code here

Sorry, you didn’t actually share any code

		jQuery(function() {
			if(jQuery('#algolia-search-box').length > 0) {

				if (algolia.indices.searchable_posts === undefined && jQuery('.admin-bar').length > 0) {
					alert('It looks like you haven\'t indexed the searchable posts index. Please head to the Indexing page of the Algolia Search plugin and index it.');
				}

				/* Instantiate instantsearch.js */
				var search = instantsearch({
					//indexName: 'staging_posts_page',
					indexName: algolia.indices.searchable_posts.name,
					searchClient: algoliasearch( algolia.application_id, algolia.search_api_key ),
					hitsPerPage: 6,
					hits: 6,
					routing: {
						router: instantsearch.routers.history({ writeDelay: 1000 }),
						stateMapping: {
							stateToRoute( indexUiState ) {
								return {
									s: indexUiState[ algolia.indices.searchable_posts.name ].query,
									page: indexUiState[ algolia.indices.searchable_posts.name ].page
								}
							},
							routeToState( routeState ) {
								const indexUiState = {};
								indexUiState[ algolia.indices.searchable_posts.name ] = {
									query: routeState.s,
									page: routeState.page
								};
								return indexUiState;
							}
						}
					}
				});

				search.addWidgets([

					/* Search box widget */
					instantsearch.widgets.searchBox({
						container: '#algolia-search-box',
						placeholder: 'Search for...',
						showReset: false,
						showSubmit: false,
						showLoadingIndicator: false,
					}),

					/* Stats widget */
					// instantsearch.widgets.stats({
					// 	container: '#algolia-stats'
					// }),

					/* Hits widget */
					instantsearch.widgets.hits({
						container: '#algolia-hits-website',
						hitsPerPage: 4,
						hits: 4,
						templates: {
							empty: 'No results were found for "<strong>{{query}}</strong>".',
							//item: '<p>{{ post_title }}</p>'
							item: wp.template('instantsearch-hits-website')
						}
					}),

				  instantsearch.widgets.index({ indexName: 'staging_posts_post' }).addWidgets([
				    instantsearch.widgets.hits({
				      container: '#algolia-hits-blog',
				      templates: {
								empty: 'No results were found for "<strong>{{query}}</strong>".',
								//item: '<p>{{ post_title }}</p>'
								item: wp.template('instantsearch-hits-blog')
				      },
				    }),
				  ]),

				  instantsearch.widgets.index({ indexName: 'staging_searchable_help' }).addWidgets([
				    instantsearch.widgets.hits({
				      container: '#algolia-hits-help',
				      templates: {
								empty: 'No results were found for "<strong>{{query}}</strong>".',
								item: wp.template('instantsearch-hits-help')
				      },
				    }),
				  ]),

				  instantsearch.widgets.index({ indexName: 'staging_searchable_app' }).addWidgets([
				    instantsearch.widgets.hits({
				      container: '#algolia-hits-app',
				      templates: {
								empty: 'No results were found for "<strong>{{query}}</strong>".',
								//item: '<p>{{ post_title }}</p>'
								item: wp.template('instantsearch-hits-app')
				      },
				    }),
				  ]),

					/* Hits widget */
					instantsearch.widgets.hits({
						container: '#algolia-hits-website',
						hitsPerPage: 10,
						templates: {
							empty: 'No results were found for "<strong>{{query}}</strong>".',
							//item: '<p>{{ post_title }}</p>'
							item: wp.template('instantsearch-hits-website')
						}
					}),

					/* Pagination widget */
					instantsearch.widgets.pagination({
						container: '#algolia-pagination',
						showNext: true,
						showPrevious: true,
						showFirst: false,
						showLast: false
					}),

					/* Pagination widget */
					instantsearch.widgets.pagination({
						container: '#algolia-pagination-website',
						showNext: true,
						showPrevious: true,
						showFirst: false,
						showLast: false
					}),

					/* Pagination widget */
					instantsearch.widgets.pagination({
						container: '#algolia-pagination-blog',
						showNext: true,
						showPrevious: true,
						showFirst: false,
						showLast: false
					}),

					/* Pagination widget */
					instantsearch.widgets.pagination({
						container: '#algolia-pagination-help',
						showNext: true,
						showPrevious: true,
						showFirst: false,
						showLast: false
					}),

					/* Pagination widget */
					instantsearch.widgets.pagination({
						container: '#algolia-pagination-app',
						showNext: true,
						showPrevious: true,
						showFirst: false,
						showLast: false
					}),

					/* Post types refinement widget */
					instantsearch.widgets.menu({
						container: '#facet-post-types',
						attribute: 'post_type_label',
						sortBy: ['count:desc', 'name:asc'],
						limit: 10,
				    templates: {
							item: ''
							//item: '<input type="checkbox" {{#isRefined}}checked{{/isRefined}}><span class="value">{{value}}</span>'
				    }
					}),

					/* Categories refinement widget */
					instantsearch.widgets.hierarchicalMenu({
						container: '#facet-categories',
						separator: ' > ',
						sortBy: ['count'],
						attributes: ['taxonomies_hierarchical.category.lvl0', 'taxonomies_hierarchical.category.lvl1', 'taxonomies_hierarchical.category.lvl2'],
					}),

					/* Tags refinement widget */
					instantsearch.widgets.refinementList({
						container: '#facet-tags',
						attribute: 'taxonomies.post_tag',
						operator: 'and',
						limit: 15,
						sortBy: ['isRefined:desc', 'count:desc', 'name:asc'],
					}),

					/* Users refinement widget */
					instantsearch.widgets.menu({
						container: '#facet-users',
						attribute: 'post_author.display_name',
						sortBy: ['isRefined:desc', 'count:desc', 'name:asc'],
						limit: 10,
					}),

					/* Search powered-by widget */
					instantsearch.widgets.poweredBy({
						container: '#algolia-powered-by'
					})
				]);

				/* Start */
				search.start();

				jQuery( '#algolia-search-box input' ).attr( 'type', 'search' ).trigger( 'select' );
			}
		});

Sorry about that - it wouldn’t post when I had the script tag at the beginning. Now I know!

This might be a better, cleaner example. This is pretty similar to what I’m doing, but I don’t know how to introduce pagination to this:

https://jsfiddle.net/j9nwpz34/

Using the 2nd example posted above has shown me what to do, I think. Both to clean up my code and to implement index-specific pagination. I’ll let you know if I need more help, but I think I’ve got this now. Thanks!

Haha nevermind, I don’t have it. The example I posted above is from an old API, v1 or v2, not sure which. So I’m still stuck.

Nevermind again, I was able to figure it out. Thanks, you can consider this issue closed.