From 876e3b3d0c94f2927decad7d1209e3fccf1a7961 Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Fri, 30 Sep 2022 16:07:54 +0200 Subject: [PATCH 1/6] Accept resultsPerPage param on the search query Co-authored-by: Camila Loiola Signed-off-by: Emma Indal --- .../search-backend/src/service/router.test.ts | 18 ++++++++++++++++++ plugins/search-backend/src/service/router.ts | 12 ++++++++++++ plugins/search-common/src/types.ts | 1 + 3 files changed, 31 insertions(+) diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index f26f191ecd..3b29e57969 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -112,6 +112,24 @@ describe('createRouter', () => { }); }); + it('should accept per page value under or equal to 100', async () => { + const response = await request(app).get(`/query?resultsPerPage=30`); + + expect(response.status).toEqual(200); + expect(response.body).toMatchObject({ + results: [], + }); + }); + + it('should reject per page value over 100', async () => { + const response = await request(app).get(`/query?resultsPerPage=200`); + + expect(response.status).toEqual(400); + expect(response.body).toMatchObject({ + error: { message: /The maximum value of the resultsPerPage param is 100, please update and make a new request/i }, + }); + }); + it('removes backend-only properties from search documents', async () => { mockSearchEngine.query.mockResolvedValue({ results: [ diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index 87da80d8f5..c0b6661f78 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -71,6 +71,7 @@ export async function createRouter( options: RouterOptions, ): Promise { const { engine: inputEngine, types, permissions, config, logger } = options; + const MAX_RESULT_PER_PAGE = 100 const requestSchema = z.object({ term: z.string().default(''), @@ -79,6 +80,17 @@ export async function createRouter( .array(z.string().refine(type => Object.keys(types).includes(type))) .optional(), pageCursor: z.string().optional(), + resultsPerPage: z + .string() + .transform((resultsPerPage) => parseInt(resultsPerPage)) + .refine( + resultsPerPage => resultsPerPage <= MAX_RESULT_PER_PAGE, + resultsPerPage => ({ + message: + `The maximum value of the resultsPerPage param is ${MAX_RESULT_PER_PAGE}, you provided ${resultsPerPage}, please update and make a new request`, + }), + ) + .optional(), }); let permissionEvaluator: PermissionEvaluator; diff --git a/plugins/search-common/src/types.ts b/plugins/search-common/src/types.ts index 4b4c25d423..1daced8e5b 100644 --- a/plugins/search-common/src/types.ts +++ b/plugins/search-common/src/types.ts @@ -26,6 +26,7 @@ export interface SearchQuery { filters?: JsonObject; types?: string[]; pageCursor?: string; + resultsPerPage?: number; } /** From 814c8a61f6413f70f2ca9cb0d279837ab6fb1bdb Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Fri, 30 Sep 2022 16:08:17 +0200 Subject: [PATCH 2/6] Search engines to use resultPerPage param if provided Co-authored-by: Camila Loiola Signed-off-by: Emma Indal --- .../src/engines/ElasticSearchSearchEngine.ts | 2 +- plugins/search-backend-node/src/engines/LunrSearchEngine.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index f3107df1fd..01d319d257 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -210,7 +210,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { .multiMatchQuery(['*'], term) .fuzziness('auto') .minimumShouldMatch(1); - const pageSize = 25; + const pageSize = query.resultsPerPage || 25; const { page } = decodePageCursor(pageCursor); let esbRequestBodySearch = esb diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index d65aa58b9d..e5d2d86168 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -71,8 +71,9 @@ export class LunrSearchEngine implements SearchEngine { term, filters, types, + resultsPerPage, }: SearchQuery): ConcreteLunrQuery => { - const pageSize = 25; + const pageSize = resultsPerPage || 25; return { lunrQueryBuilder: q => { From 60a912cd2cbdf43177d2952210333b5c7e3e7621 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 30 Sep 2022 20:23:00 +0200 Subject: [PATCH 3/6] Rename param to page limit and validate its type Signed-off-by: Camila Belo --- .../src/engines/ElasticSearchSearchEngine.ts | 2 +- .../src/engines/LunrSearchEngine.ts | 4 ++-- .../search-backend/src/service/router.test.ts | 19 ++++++++++++++++--- plugins/search-backend/src/service/router.ts | 19 ++++++++++++------- plugins/search-common/src/types.ts | 4 ++-- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index 01d319d257..a33d8939eb 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -210,7 +210,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { .multiMatchQuery(['*'], term) .fuzziness('auto') .minimumShouldMatch(1); - const pageSize = query.resultsPerPage || 25; + const pageSize = query.pageLimit || 25; const { page } = decodePageCursor(pageCursor); let esbRequestBodySearch = esb diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index e5d2d86168..d60f9951f4 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -71,9 +71,9 @@ export class LunrSearchEngine implements SearchEngine { term, filters, types, - resultsPerPage, + pageLimit, }: SearchQuery): ConcreteLunrQuery => { - const pageSize = resultsPerPage || 25; + const pageSize = pageLimit || 25; return { lunrQueryBuilder: q => { diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index 3b29e57969..c3eb6ea00f 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -113,7 +113,7 @@ describe('createRouter', () => { }); it('should accept per page value under or equal to 100', async () => { - const response = await request(app).get(`/query?resultsPerPage=30`); + const response = await request(app).get(`/query?pageLimit=30`); expect(response.status).toEqual(200); expect(response.body).toMatchObject({ @@ -122,11 +122,24 @@ describe('createRouter', () => { }); it('should reject per page value over 100', async () => { - const response = await request(app).get(`/query?resultsPerPage=200`); + const response = await request(app).get(`/query?pageLimit=200`); expect(response.status).toEqual(400); expect(response.body).toMatchObject({ - error: { message: /The maximum value of the resultsPerPage param is 100, please update and make a new request/i }, + error: { + message: /The page limit "200" is greater than "100"/i, + }, + }); + }); + + it('should reject a non number per page value', async () => { + const response = await request(app).get(`/query?pageLimit=twohundred`); + + expect(response.status).toEqual(400); + expect(response.body).toMatchObject({ + error: { + message: /The page limit "twohundred" is not a number"/i, + }, }); }); diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index c0b6661f78..5ad4d4969b 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -62,6 +62,7 @@ export type RouterOptions = { logger: Logger; }; +const maxPageLimit = 100; const allowedLocationProtocols = ['http:', 'https:']; /** @@ -71,7 +72,6 @@ export async function createRouter( options: RouterOptions, ): Promise { const { engine: inputEngine, types, permissions, config, logger } = options; - const MAX_RESULT_PER_PAGE = 100 const requestSchema = z.object({ term: z.string().default(''), @@ -80,14 +80,19 @@ export async function createRouter( .array(z.string().refine(type => Object.keys(types).includes(type))) .optional(), pageCursor: z.string().optional(), - resultsPerPage: z + pageLimit: z .string() - .transform((resultsPerPage) => parseInt(resultsPerPage)) + .transform(pageLimit => parseInt(pageLimit, 10)) .refine( - resultsPerPage => resultsPerPage <= MAX_RESULT_PER_PAGE, - resultsPerPage => ({ - message: - `The maximum value of the resultsPerPage param is ${MAX_RESULT_PER_PAGE}, you provided ${resultsPerPage}, please update and make a new request`, + pageLimit => !isNaN(pageLimit), + pageLimit => ({ + message: `The page limit "${pageLimit}" is not a number`, + }), + ) + .refine( + pageLimit => pageLimit <= maxPageLimit, + pageLimit => ({ + message: `The page limit "${pageLimit}" is greater than "${maxPageLimit}"`, }), ) .optional(), diff --git a/plugins/search-common/src/types.ts b/plugins/search-common/src/types.ts index 1daced8e5b..54abc9e1b1 100644 --- a/plugins/search-common/src/types.ts +++ b/plugins/search-common/src/types.ts @@ -23,10 +23,10 @@ import { Readable, Transform, Writable } from 'stream'; */ export interface SearchQuery { term: string; - filters?: JsonObject; types?: string[]; + filters?: JsonObject; + pageLimit?: number; pageCursor?: string; - resultsPerPage?: number; } /** From d7200e4d91769c62eb90ac7485b3383f8e17087b Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 3 Oct 2022 10:06:01 +0200 Subject: [PATCH 4/6] Add page limit to search context and state Signed-off-by: Camila Belo --- .../components/SearchResult/SearchResult.tsx | 14 +- .../src/context/SearchContext.test.tsx | 138 +++++++++++------- .../src/context/SearchContext.tsx | 25 +++- 3 files changed, 105 insertions(+), 72 deletions(-) diff --git a/plugins/search-react/src/components/SearchResult/SearchResult.tsx b/plugins/search-react/src/components/SearchResult/SearchResult.tsx index 40c60c3263..dd11f42903 100644 --- a/plugins/search-react/src/components/SearchResult/SearchResult.tsx +++ b/plugins/search-react/src/components/SearchResult/SearchResult.tsx @@ -98,16 +98,10 @@ export const SearchResultApi = (props: SearchResultApiProps) => { const { query, children } = props; const searchApi = useApi(searchApiRef); - const state = useAsync( - () => - searchApi.query({ - term: query.term ?? '', - types: query.types ?? [], - filters: query.filters ?? {}, - pageCursor: query.pageCursor, - }), - [query], - ); + const state = useAsync(() => { + const { term = '', types = [], filters = {}, ...rest } = query; + return searchApi.query({ ...rest, term, types, filters }); + }, [query]); return children(state); }; diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index b5888fa8a9..edee2f153f 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -40,8 +40,8 @@ describe('SearchContext', () => { const initialState = { term: '', - filters: {}, types: ['*'], + filters: {}, }; beforeEach(() => { @@ -167,8 +167,8 @@ describe('SearchContext', () => { initialProps: { initialState: { ...initialState, - filters: { foo: 'bar' }, term: 'first term', + filters: { foo: 'bar' }, pageCursor: 'SOMEPAGE', }, }, @@ -194,8 +194,8 @@ describe('SearchContext', () => { initialProps: { initialState: { ...initialState, - filters: { foo: 'bar' }, term: 'first term', + filters: { foo: 'bar' }, pageCursor: 'SOMEPAGE', }, }, @@ -236,58 +236,9 @@ describe('SearchContext', () => { await waitForNextUpdate(); expect(query).toHaveBeenLastCalledWith({ - filters: {}, - types: ['*'], term, - }); - }); - - it('When filters are set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, - }); - - await waitForNextUpdate(); - - const filters = { filter: 'filter' }; - - act(() => { - result.current.setFilters(filters); - }); - - await waitForNextUpdate(); - - expect(query).toHaveBeenLastCalledWith({ - filters, types: ['*'], - term: '', - }); - }); - - it('When page is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, - }); - - await waitForNextUpdate(); - - act(() => { - result.current.setPageCursor('SOMEPAGE'); - }); - - await waitForNextUpdate(); - - expect(query).toHaveBeenLastCalledWith({ filters: {}, - types: ['*'], - pageCursor: 'SOMEPAGE', - term: '', }); }); @@ -311,8 +262,85 @@ describe('SearchContext', () => { expect(query).toHaveBeenLastCalledWith({ types, - filters: {}, term: '', + filters: {}, + }); + }); + + it('When filters are set', async () => { + const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + wrapper, + initialProps: { + initialState, + }, + }); + + await waitForNextUpdate(); + + const filters = { filter: 'filter' }; + + act(() => { + result.current.setFilters(filters); + }); + + await waitForNextUpdate(); + + expect(query).toHaveBeenLastCalledWith({ + filters, + term: '', + types: ['*'], + }); + }); + + it('When page limit is set', async () => { + const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + wrapper, + initialProps: { + initialState, + }, + }); + + await waitForNextUpdate(); + + const pageLimit = 30; + + act(() => { + result.current.setPageLimit(pageLimit); + }); + + await waitForNextUpdate(); + + expect(query).toHaveBeenLastCalledWith({ + pageLimit, + term: '', + types: ['*'], + filters: {}, + }); + }); + + it('When page cursor is set', async () => { + const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + wrapper, + initialProps: { + initialState, + }, + }); + + await waitForNextUpdate(); + + const pageCursor = 'SOMEPAGE'; + + act(() => { + result.current.setPageCursor(pageCursor); + }); + + await waitForNextUpdate(); + + expect(query).toHaveBeenLastCalledWith({ + pageCursor, + term: '', + types: ['*'], + filters: {}, }); }); @@ -341,9 +369,9 @@ describe('SearchContext', () => { await waitForNextUpdate(); expect(query).toHaveBeenLastCalledWith({ + term: '', types: ['*'], filters: {}, - term: '', pageCursor: 'NEXT', }); }); @@ -373,9 +401,9 @@ describe('SearchContext', () => { await waitForNextUpdate(); expect(query).toHaveBeenLastCalledWith({ + term: '', types: ['*'], filters: {}, - term: '', pageCursor: 'PREVIOUS', }); }); diff --git a/plugins/search-react/src/context/SearchContext.tsx b/plugins/search-react/src/context/SearchContext.tsx index 6557f04c15..94e51c0668 100644 --- a/plugins/search-react/src/context/SearchContext.tsx +++ b/plugins/search-react/src/context/SearchContext.tsx @@ -44,6 +44,7 @@ export type SearchContextValue = { setTerm: React.Dispatch>; setTypes: React.Dispatch>; setFilters: React.Dispatch>; + setPageLimit: React.Dispatch>; setPageCursor: React.Dispatch>; fetchNextPage?: React.DispatchWithoutAction; fetchPreviousPage?: React.DispatchWithoutAction; @@ -57,6 +58,7 @@ export type SearchContextState = { term: string; types: string[]; filters: JsonObject; + pageLimit?: number; pageCursor?: string; }; @@ -98,9 +100,10 @@ export const useSearchContextCheck = () => { */ const searchInitialState: SearchContextState = { term: '', - pageCursor: undefined, - filters: {}, types: [], + filters: {}, + pageLimit: undefined, + pageCursor: undefined, }; const useSearchContextValue = ( @@ -111,6 +114,9 @@ const useSearchContextValue = ( const [term, setTerm] = useState(initialValue.term); const [types, setTypes] = useState(initialValue.types); const [filters, setFilters] = useState(initialValue.filters); + const [pageLimit, setPageLimit] = useState( + initialValue.pageLimit, + ); const [pageCursor, setPageCursor] = useState( initialValue.pageCursor, ); @@ -122,20 +128,23 @@ const useSearchContextValue = ( () => searchApi.query({ term, - filters, - pageCursor, types, + filters, + pageLimit, + pageCursor, }), - [term, types, filters, pageCursor], + [term, types, filters, pageLimit, pageCursor], ); const hasNextPage = !result.loading && !result.error && result.value?.nextPageCursor; const hasPreviousPage = !result.loading && !result.error && result.value?.previousPageCursor; + const fetchNextPage = useCallback(() => { setPageCursor(result.value?.nextPageCursor); }, [result.value?.nextPageCursor]); + const fetchPreviousPage = useCallback(() => { setPageCursor(result.value?.previousPageCursor); }, [result.value?.previousPageCursor]); @@ -158,12 +167,14 @@ const useSearchContextValue = ( const value: SearchContextValue = { result, - filters, - setFilters, term, setTerm, types, setTypes, + filters, + setFilters, + pageLimit, + setPageLimit, pageCursor, setPageCursor, fetchNextPage: hasNextPage ? fetchNextPage : undefined, From a799972bb12808cb6c8cc68fda4d69fd9ec4d461 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 3 Oct 2022 10:09:32 +0200 Subject: [PATCH 5/6] Update api reports and add changeset files Signed-off-by: Camila Belo --- .changeset/search-cars-hide.md | 5 +++++ .changeset/search-cycles-sniff.md | 5 +++++ .changeset/search-days-pull.md | 5 +++++ .changeset/search-otters-destroy.md | 5 +++++ .changeset/search-rats-grin.md | 14 ++++++++++++++ plugins/search-common/api-report.md | 2 ++ plugins/search-react/api-report.md | 2 ++ 7 files changed, 38 insertions(+) create mode 100644 .changeset/search-cars-hide.md create mode 100644 .changeset/search-cycles-sniff.md create mode 100644 .changeset/search-days-pull.md create mode 100644 .changeset/search-otters-destroy.md create mode 100644 .changeset/search-rats-grin.md diff --git a/.changeset/search-cars-hide.md b/.changeset/search-cars-hide.md new file mode 100644 index 0000000000..b89662e90a --- /dev/null +++ b/.changeset/search-cars-hide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-common': minor +--- + +There is a new property called `pageLimit` on the `SearchQuery` interface that specifies how many results should be returned per page. diff --git a/.changeset/search-cycles-sniff.md b/.changeset/search-cycles-sniff.md new file mode 100644 index 0000000000..e422d50806 --- /dev/null +++ b/.changeset/search-cycles-sniff.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': minor +--- + +The `Elastic Search` search engine query now contains a property called `pageLimit`, this new property specifies how many results to return per page and its default value is 25. diff --git a/.changeset/search-days-pull.md b/.changeset/search-days-pull.md new file mode 100644 index 0000000000..3a3c09d5bb --- /dev/null +++ b/.changeset/search-days-pull.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': minor +--- + +Added new page boundary to search query context and results state. diff --git a/.changeset/search-otters-destroy.md b/.changeset/search-otters-destroy.md new file mode 100644 index 0000000000..b91b98c173 --- /dev/null +++ b/.changeset/search-otters-destroy.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-node': minor +--- + +The `Lunr` search engine query now contains a property called `pageLimit`, this new property specifies how many results to return per page and its default value is 25. diff --git a/.changeset/search-rats-grin.md b/.changeset/search-rats-grin.md new file mode 100644 index 0000000000..16d4e293c0 --- /dev/null +++ b/.changeset/search-rats-grin.md @@ -0,0 +1,14 @@ +--- +'@backstage/plugin-search-backend': minor +--- + +The query received by search engines now contains a property called `pageLimit`, it specifies how many results to return per page when sending a query request to the search backend. + +Example: +_Returns up to 30 results per page_ + +``` +GET /query?pageLimit=30 +``` + +It is worth mentioning that only the Lunr and Elastic Search engines currently use this new property in their implementations. So that means you can't use it with Postgres for now. The search backend doesn't set a default value for the page limit parameter, it leaves it up to each search engine to set this, so Lunr and Elastic Search set 25 results per page as a default value. diff --git a/plugins/search-common/api-report.md b/plugins/search-common/api-report.md index ea9fc2d26e..61e5d22257 100644 --- a/plugins/search-common/api-report.md +++ b/plugins/search-common/api-report.md @@ -102,6 +102,8 @@ export interface SearchQuery { // (undocumented) pageCursor?: string; // (undocumented) + pageLimit?: number; + // (undocumented) term: string; // (undocumented) types?: string[]; diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index 1160675c5a..ddfe5d5b39 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -165,6 +165,7 @@ export type SearchContextState = { term: string; types: string[]; filters: JsonObject; + pageLimit?: number; pageCursor?: string; }; @@ -174,6 +175,7 @@ export type SearchContextValue = { setTerm: React_2.Dispatch>; setTypes: React_2.Dispatch>; setFilters: React_2.Dispatch>; + setPageLimit: React_2.Dispatch>; setPageCursor: React_2.Dispatch>; fetchNextPage?: React_2.DispatchWithoutAction; fetchPreviousPage?: React_2.DispatchWithoutAction; From 4ed1fa24809f93844325f6ac0a38490a5acf12f3 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 3 Oct 2022 13:50:14 +0200 Subject: [PATCH 6/6] refactor: apply review suggestions Signed-off-by: Camila Belo --- .changeset/search-bobcats-love.md | 28 +++++++++++++++++++ .changeset/search-cycles-sniff.md | 6 ++-- .changeset/search-days-pull.md | 5 ---- .changeset/search-otters-destroy.md | 5 ---- .changeset/search-rats-grin.md | 2 +- .../src/PgSearchEngine/PgSearchEngine.ts | 2 +- 6 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 .changeset/search-bobcats-love.md delete mode 100644 .changeset/search-days-pull.md delete mode 100644 .changeset/search-otters-destroy.md diff --git a/.changeset/search-bobcats-love.md b/.changeset/search-bobcats-love.md new file mode 100644 index 0000000000..f562961c1b --- /dev/null +++ b/.changeset/search-bobcats-love.md @@ -0,0 +1,28 @@ +--- +'@backstage/plugin-search-react': minor +--- + +The search query state now has an optional `pageLimit` property that determines how many results will be requested per page, it defaults to 25. + +Examples: +_Basic_ + +```jsx + + {results => { + // Item rendering logic is omitted + }} + +``` + +_With context_ + +```jsx + + + {results => { + // Item rendering logic is omitted + }} + + +``` diff --git a/.changeset/search-cycles-sniff.md b/.changeset/search-cycles-sniff.md index e422d50806..350e499a18 100644 --- a/.changeset/search-cycles-sniff.md +++ b/.changeset/search-cycles-sniff.md @@ -1,5 +1,7 @@ --- -'@backstage/plugin-search-backend-module-elasticsearch': minor +'@backstage/plugin-search-backend-node': patch +'@backstage/plugin-search-backend-module-pg': patch +'@backstage/plugin-search-backend-module-elasticsearch': patch --- -The `Elastic Search` search engine query now contains a property called `pageLimit`, this new property specifies how many results to return per page and its default value is 25. +The search engine has been updated to take advantage of the `pageLimit` property on search queries. If none is provided, the search engine will continue to use its default value of 25 results per page. diff --git a/.changeset/search-days-pull.md b/.changeset/search-days-pull.md deleted file mode 100644 index 3a3c09d5bb..0000000000 --- a/.changeset/search-days-pull.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-react': minor ---- - -Added new page boundary to search query context and results state. diff --git a/.changeset/search-otters-destroy.md b/.changeset/search-otters-destroy.md deleted file mode 100644 index b91b98c173..0000000000 --- a/.changeset/search-otters-destroy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend-node': minor ---- - -The `Lunr` search engine query now contains a property called `pageLimit`, this new property specifies how many results to return per page and its default value is 25. diff --git a/.changeset/search-rats-grin.md b/.changeset/search-rats-grin.md index 16d4e293c0..7b561d9c19 100644 --- a/.changeset/search-rats-grin.md +++ b/.changeset/search-rats-grin.md @@ -11,4 +11,4 @@ _Returns up to 30 results per page_ GET /query?pageLimit=30 ``` -It is worth mentioning that only the Lunr and Elastic Search engines currently use this new property in their implementations. So that means you can't use it with Postgres for now. The search backend doesn't set a default value for the page limit parameter, it leaves it up to each search engine to set this, so Lunr and Elastic Search set 25 results per page as a default value. +The search backend validates the page limit and this value must not exceed 100, but it doesn't set a default value for the page limit parameter, it leaves it up to each search engine to set this, so Lunr, Postgres and Elastic Search set 25 results per page as a default value. diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts index 01fe0fff82..f53c433c2f 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts @@ -137,7 +137,7 @@ export class PgSearchEngine implements SearchEngine { query: SearchQuery, options: PgSearchQueryTranslatorOptions, ): ConcretePgSearchQuery { - const pageSize = 25; + const pageSize = query.pageLimit || 25; const { page } = decodePageCursor(query.pageCursor); const offset = page * pageSize; // We request more result to know whether there is another page