From eaf1bf9aaa71dacd038d188193bc4d7c7f516449 Mon Sep 17 00:00:00 2001 From: Conrad VanLandingham Date: Tue, 9 Apr 2024 08:57:00 -0500 Subject: [PATCH] Improve search result sorting and add subtitles to results --- .../components/Searchbar/Autocomplete.js | 2 + .../components/Searchbar/SearchResults.js | 109 ++++++++++++------ 2 files changed, 75 insertions(+), 36 deletions(-) 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 !== '' ? ( -
    -
      - {items.map((item) => ( - - { - if (collection.source.sourceId === 'pages') { - return handleStaticActionPress(item); - } - return handleActionPress(item); - }} - background="none" - /> - - ))} -
    -
    - ) : null; })} + { + // Rendering of regular items + autocompleteState.query !== '' ? ( +
    +
      + {allResults.map((item) => ( + + { + if (collection.source.sourceId === 'pages') { + return handleStaticActionPress(item); + } + return handleActionPress(item); + }} + background="none" + /> + + ))} +
    +
    + ) : null + } {autocompleteState.isOpen && autocompleteState.query === '' && searchState.searchFeed ? (