diff --git a/packages/web-shared/components/Searchbar/Autocomplete.js b/packages/web-shared/components/Searchbar/Autocomplete.js index 8e223079..8b5edc1d 100644 --- a/packages/web-shared/components/Searchbar/Autocomplete.js +++ b/packages/web-shared/components/Searchbar/Autocomplete.js @@ -152,6 +152,7 @@ export default function Autocomplete({ facetFilters: [`church:${searchState.church}`], hitsPerPage: 4, clickAnalytics: true, + getRankingInfo: true, // highlightPreTag: '', // highlightPostTag: '', }, @@ -182,6 +183,7 @@ export default function Autocomplete({ params: { hitsPerPage: 8, clickAnalytics: true, + getRankingInfo: true, // highlightPreTag: '', // highlightPostTag: '', }, diff --git a/packages/web-shared/components/Searchbar/SearchResults.js b/packages/web-shared/components/Searchbar/SearchResults.js index b2ff779e..792517cc 100644 --- a/packages/web-shared/components/Searchbar/SearchResults.js +++ b/packages/web-shared/components/Searchbar/SearchResults.js @@ -171,6 +171,39 @@ const SearchResults = ({ autocompleteState, autocomplete }) => { // Makes SSR consistent on aria aspects const inputProps = autocomplete.getInputProps({}); + // Hack: join results from each collection back to a single array, and re-sort them by Algolia's ranking + // TODO: Remove once we have a single index for all content + const allResults = []; + autocompleteState.collections + .filter((collection) => ['pages', 'content'].includes(collection.source.sourceId)) + .forEach((collection) => { + allResults.push(...collection.items.map((item) => ({ ...item, source: collection.source }))); + }); + // Algolia adds a _rankingInfo property to each item, which we can use to sort the results + // We want to sort the results first by nbExactWords (desc), then proximityDistance (asc), then last by userScore (desc) + // This is super hacky and results are not to be guaranteed, but should improve results over displaying them in the order they come back + allResults.sort((a, b) => { + if (a._rankingInfo.nbExactWords > b._rankingInfo.nbExactWords) { + return -1; + } + if (a._rankingInfo.nbExactWords < b._rankingInfo.nbExactWords) { + return 1; + } + if (a._rankingInfo.proximityDistance < b._rankingInfo.proximityDistance) { + return -1; + } + if (a._rankingInfo.proximityDistance > b._rankingInfo.proximityDistance) { + return 1; + } + if (a._rankingInfo.userScore > b._rankingInfo.userScore) { + return -1; + } + if (a._rankingInfo.userScore < b._rankingInfo.userScore) { + return 1; + } + return 0; + }); + return ( { Trending Searches )} - {collection.source.sourceId === 'recentSearchesPlugin' && ( + {collection.source.sourceId === 'recentSearchesPlugin' && !inputProps.value && ( Search History @@ -240,7 +273,10 @@ const SearchResults = ({ autocompleteState, autocomplete }) => { /> ); - } else if (collection.source.sourceId === 'recentSearchesPlugin') { + } else if ( + collection.source.sourceId === 'recentSearchesPlugin' && + !inputProps.value + ) { return (
  • { ); } - - // Rendering of regular items - - return autocompleteState.query !== '' ? ( -
    - -
    - ) : null; })} + { + // Rendering of regular items + autocompleteState.query !== '' ? ( +
    + +
    + ) : null + } {autocompleteState.isOpen && autocompleteState.query === '' && searchState.searchFeed ? (