docs: improve search to show results for all filters (#9208)
* docs: improve search to show results for all filters * fix index ordering
This commit is contained in:
@@ -21,8 +21,8 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
mainIndexName:
|
mainIndexName:
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
indices: [
|
indices: [
|
||||||
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
searchProps={{
|
searchProps={{
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
mainIndexName:
|
mainIndexName:
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
indices: [
|
indices: [
|
||||||
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
searchProps={{
|
searchProps={{
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export const SearchHits = ({
|
|||||||
setNoResults,
|
setNoResults,
|
||||||
checkInternalPattern,
|
checkInternalPattern,
|
||||||
}: SearchHitsProps) => {
|
}: SearchHitsProps) => {
|
||||||
const { hits } = useHits<HitType>()
|
const { items: hits } = useHits<HitType>()
|
||||||
const { status } = useInstantSearch()
|
const { status } = useInstantSearch()
|
||||||
const { setIsOpen } = useSearch()
|
const { setIsOpen } = useSearch()
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import { checkArraySameElms } from "../../utils"
|
|||||||
import {
|
import {
|
||||||
liteClient as algoliasearch,
|
liteClient as algoliasearch,
|
||||||
LiteClient as SearchClient,
|
LiteClient as SearchClient,
|
||||||
|
type SearchResponses,
|
||||||
|
type SearchHits,
|
||||||
|
SearchResponse,
|
||||||
} from "algoliasearch/lite"
|
} from "algoliasearch/lite"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import { CSSTransition, SwitchTransition } from "react-transition-group"
|
import { CSSTransition, SwitchTransition } from "react-transition-group"
|
||||||
@@ -78,11 +81,37 @@ export const SearchProvider = ({
|
|||||||
async search(searchParams) {
|
async search(searchParams) {
|
||||||
const requests =
|
const requests =
|
||||||
"requests" in searchParams ? searchParams.requests : searchParams
|
"requests" in searchParams ? searchParams.requests : searchParams
|
||||||
const noQueries = requests.every(
|
// always send this request, which is the main request with no filters
|
||||||
|
const mainRequest = requests[0]
|
||||||
|
|
||||||
|
// retrieve only requests that have filters
|
||||||
|
// this is to ensure that we show no result if no filter is selected
|
||||||
|
const requestsWithFilters = requests.filter((item) => {
|
||||||
|
if (
|
||||||
|
!item.params ||
|
||||||
|
typeof item.params !== "object" ||
|
||||||
|
!("tagFilters" in item.params)
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagFilters = item.params.tagFilters as string[]
|
||||||
|
|
||||||
|
// if no tag filters are specified, there's still one item,
|
||||||
|
// which is an empty array
|
||||||
|
return tagFilters.length >= 1 && tagFilters[0].length > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// check whether a query is entered in the search box
|
||||||
|
const noQueries = requestsWithFilters.every(
|
||||||
(item) =>
|
(item) =>
|
||||||
("facetQuery" in item && !item.facetQuery) ||
|
!item.facetQuery &&
|
||||||
("query" in item && !item.query)
|
(!item.params ||
|
||||||
|
typeof item.params !== "object" ||
|
||||||
|
!("query" in item.params) ||
|
||||||
|
!item.params.query)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (noQueries) {
|
if (noQueries) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
results: requests.map(() => ({
|
results: requests.map(() => ({
|
||||||
@@ -99,7 +128,73 @@ export const SearchProvider = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return algoliaClient.search(searchParams)
|
// split requests per tags
|
||||||
|
const newRequests: typeof requestsWithFilters = [mainRequest]
|
||||||
|
for (const request of requestsWithFilters) {
|
||||||
|
const params = request.params as Record<string, unknown>
|
||||||
|
const tagFilters = (params.tagFilters as string[][])[0]
|
||||||
|
|
||||||
|
// if only one tag is selected, keep the request as-is
|
||||||
|
if (tagFilters.length === 1) {
|
||||||
|
newRequests.push(request)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if multiple tags are selected, split the tags
|
||||||
|
// to retrieve a small subset of results per each tag.
|
||||||
|
newRequests.push(
|
||||||
|
...tagFilters.map((tag) => ({
|
||||||
|
...request,
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
tagFilters: [tag],
|
||||||
|
},
|
||||||
|
hitsPerPage: 4,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return algoliaClient
|
||||||
|
.search<SearchHits>(newRequests)
|
||||||
|
.then((response) => {
|
||||||
|
// combine results of the same index and return the results
|
||||||
|
const resultsByIndex: {
|
||||||
|
[indexName: string]: SearchResponse<SearchHits>
|
||||||
|
} = {}
|
||||||
|
// extract the response of the main request
|
||||||
|
const mainResult = response.results[0]
|
||||||
|
|
||||||
|
response.results.forEach((result, indexNum) => {
|
||||||
|
if (indexNum === 0) {
|
||||||
|
// ignore the main request's result
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const resultIndex = "index" in result ? result.index : undefined
|
||||||
|
const resultHits = "hits" in result ? result.hits : []
|
||||||
|
|
||||||
|
if (!resultIndex) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resultsByIndex[resultIndex] = {
|
||||||
|
...result,
|
||||||
|
...(resultsByIndex[resultIndex] || {}),
|
||||||
|
hits: [
|
||||||
|
...(resultsByIndex[resultIndex]?.hits || []),
|
||||||
|
...resultHits,
|
||||||
|
],
|
||||||
|
nbHits:
|
||||||
|
(resultsByIndex[resultIndex]?.nbHits || 0) +
|
||||||
|
resultHits.length,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
// append the results with the main request's results
|
||||||
|
results: [mainResult, ...Object.values(resultsByIndex)],
|
||||||
|
} as SearchResponses<any>
|
||||||
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}, [algolia.appId, algolia.apiKey])
|
}, [algolia.appId, algolia.apiKey])
|
||||||
|
|||||||
Reference in New Issue
Block a user