diff --git a/src/adapter/search-request-adapter/__tests__/search-params.tests.ts b/src/adapter/search-request-adapter/__tests__/search-params.tests.ts index 3e0a3aa1..b4c3de7a 100644 --- a/src/adapter/search-request-adapter/__tests__/search-params.tests.ts +++ b/src/adapter/search-request-adapter/__tests__/search-params.tests.ts @@ -5,6 +5,8 @@ const DEFAULT_CONTEXT = { indexUid: 'test', pagination: { page: 0, hitsPerPage: 6, finite: false }, defaultFacetDistribution: {}, + placeholderSearch: true, + keepZeroFacets: false, } describe('Parameters adapter', () => { @@ -155,6 +157,31 @@ describe('Pagination adapter', () => { expect(searchParams.hitsPerPage).toBe(0) }) + test('adapting a finite pagination with no placeholderSearch and a query', () => { + const searchParams = adaptSearchParams({ + ...DEFAULT_CONTEXT, + query: 'a', + pagination: { page: 4, hitsPerPage: 6, finite: true }, + placeholderSearch: false, + }) + + expect(searchParams.page).toBe(5) + expect(searchParams.hitsPerPage).toBeGreaterThan(0) + }) + + test('adapting a finite pagination with no placeholderSearch and a facetFilter', () => { + const searchParams = adaptSearchParams({ + ...DEFAULT_CONTEXT, + query: '', + pagination: { page: 4, hitsPerPage: 6, finite: true }, + placeholderSearch: false, + facetFilters: ['genres:Action'], + }) + + expect(searchParams.page).toBe(5) + expect(searchParams.hitsPerPage).toBeGreaterThan(0) + }) + test('adapting a scroll pagination with no placeholderSearch', () => { const searchParams = adaptSearchParams({ ...DEFAULT_CONTEXT, @@ -166,4 +193,29 @@ describe('Pagination adapter', () => { expect(searchParams.limit).toBe(0) expect(searchParams.offset).toBe(0) }) + + test('adapting a scroll pagination with no placeholderSearch and a query', () => { + const searchParams = adaptSearchParams({ + ...DEFAULT_CONTEXT, + query: 'a', + pagination: { page: 4, hitsPerPage: 6, finite: false }, + placeholderSearch: false, + }) + + expect(searchParams.limit).toBeGreaterThan(0) + expect(searchParams.offset).toBeGreaterThan(0) + }) + + test('adapting a scroll pagination with no placeholderSearch and a facetFilter', () => { + const searchParams = adaptSearchParams({ + ...DEFAULT_CONTEXT, + query: 'a', + pagination: { page: 4, hitsPerPage: 6, finite: false }, + placeholderSearch: false, + facetFilters: ['genres:Action'], + }) + + expect(searchParams.limit).toBeGreaterThan(0) + expect(searchParams.offset).toBeGreaterThan(0) + }) }) diff --git a/src/adapter/search-request-adapter/search-params-adapter.ts b/src/adapter/search-request-adapter/search-params-adapter.ts index b012acff..936957bf 100644 --- a/src/adapter/search-request-adapter/search-params-adapter.ts +++ b/src/adapter/search-request-adapter/search-params-adapter.ts @@ -1,4 +1,9 @@ -import type { MeiliSearchParams, SearchContext } from '../../types' +import type { + MeiliSearchParams, + SearchContext, + Filter, + PaginationState, +} from '../../types' import { adaptGeoPointsRules, @@ -6,13 +11,28 @@ import { } from './geo-rules-adapter' import { adaptFilters } from './filter-adapter' -function setScrollPagination( - hitsPerPage: number, - page: number, +function isPaginationRequired( + filter: Filter, query?: string, placeholderSearch?: boolean +): boolean { + // To disable pagination: + // placeholderSearch must be disabled + // The search query must be empty + // There must be no filters + if (!placeholderSearch && !query && (!filter || filter.length === 0)) { + return false + } + return true +} + +function setScrollPagination( + pagination: PaginationState, + paginationRequired: boolean ): { limit: number; offset: number } { - if (!placeholderSearch && query === '') { + const { page, hitsPerPage } = pagination + + if (!paginationRequired) { return { limit: 0, offset: 0, @@ -26,12 +46,12 @@ function setScrollPagination( } function setFinitePagination( - hitsPerPage: number, - page: number, - query?: string, - placeholderSearch?: boolean + pagination: PaginationState, + paginationRequired: boolean ): { hitsPerPage: number; page: number } { - if (!placeholderSearch && query === '') { + const { page, hitsPerPage } = pagination + + if (!paginationRequired) { return { hitsPerPage: 0, page: page + 1, @@ -58,9 +78,6 @@ export function MeiliParamsCreator(searchContext: SearchContext) { attributesToSnippet, snippetEllipsisText, attributesToRetrieve, - filters, - numericFilters, - facetFilters, attributesToHighlight, highlightPreTag, highlightPostTag, @@ -69,8 +86,13 @@ export function MeiliParamsCreator(searchContext: SearchContext) { sort, pagination, matchingStrategy, + filters, + numericFilters, + facetFilters, } = searchContext + const meilisearchFilters = adaptFilters(filters, numericFilters, facetFilters) + return { getParams() { return meiliSearchParams @@ -99,9 +121,8 @@ export function MeiliParamsCreator(searchContext: SearchContext) { } }, addFilters() { - const filter = adaptFilters(filters, numericFilters, facetFilters) - if (filter.length) { - meiliSearchParams.filter = filter + if (meilisearchFilters.length) { + meiliSearchParams.filter = meilisearchFilters } }, addAttributesToHighlight() { @@ -122,21 +143,22 @@ export function MeiliParamsCreator(searchContext: SearchContext) { } }, addPagination() { + const paginationRequired = isPaginationRequired( + meilisearchFilters, + query, + placeholderSearch + ) if (pagination.finite) { const { hitsPerPage, page } = setFinitePagination( - pagination.hitsPerPage, - pagination.page, - query, - placeholderSearch + pagination, + paginationRequired ) meiliSearchParams.hitsPerPage = hitsPerPage meiliSearchParams.page = page } else { const { limit, offset } = setScrollPagination( - pagination.hitsPerPage, - pagination.page, - query, - placeholderSearch + pagination, + paginationRequired ) meiliSearchParams.limit = limit meiliSearchParams.offset = offset diff --git a/src/adapter/search-request-adapter/search-resolver.ts b/src/adapter/search-request-adapter/search-resolver.ts index 2805b3e9..08ba6683 100644 --- a/src/adapter/search-request-adapter/search-resolver.ts +++ b/src/adapter/search-request-adapter/search-resolver.ts @@ -25,8 +25,6 @@ export function SearchResolver( searchContext: SearchContext, searchParams: MeiliSearchParams ): Promise>> { - const { placeholderSearch, query } = searchContext - // Create cache key containing a unique set of search parameters const key = cache.formatKey([ searchParams, @@ -54,13 +52,9 @@ export function SearchResolver( ) } - // query can be: empty string, undefined or null - // all of them are falsy's - if (!placeholderSearch && !query) { - searchResponse.hits = [] - } // Cache response cache.setEntry(key, searchResponse) + return searchResponse }, } diff --git a/src/types/types.ts b/src/types/types.ts index ebd7b890..2d3a4fb4 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -78,11 +78,11 @@ export type SearchContext = Omit & defaultFacetDistribution: FacetDistribution pagination: PaginationState indexUid: string + placeholderSearch: boolean + keepZeroFacets: boolean insideBoundingBox?: InsideBoundingBox - keepZeroFacets?: boolean cropMarker?: string sort?: string - placeholderSearch?: boolean primaryKey?: string matchingStrategy?: MatchingStrategies } diff --git a/tests/placeholder-search.tests.ts b/tests/placeholder-search.tests.ts index 16c4dac4..e28b0c98 100644 --- a/tests/placeholder-search.tests.ts +++ b/tests/placeholder-search.tests.ts @@ -51,4 +51,48 @@ describe('Pagination browser test', () => { const hits = response.results[0].hits expect(hits.length).toBe(0) }) + + test('placeholdersearch with query', async () => { + const customClient = instantMeiliSearch( + 'http://localhost:7700', + 'masterKey', + { + placeholderSearch: false, + } + ) + + const response = await customClient.search([ + { + indexName: 'movies', + params: { + query: 'a', + }, + }, + ]) + + const hits = response.results[0].hits + expect(hits.length).toBeGreaterThan(0) + }) + + test('placeholdersearch set to false with filter', async () => { + const customClient = instantMeiliSearch( + 'http://localhost:7700', + 'masterKey', + { + placeholderSearch: false, + } + ) + + const response = await customClient.search([ + { + indexName: 'movies', + params: { + facetFilters: ['genres:Action'], + }, + }, + ]) + + const hits = response.results[0].hits + expect(hits.length).toBeGreaterThan(0) + }) })