From 99f0845b98caf0a5b339c7ce1c00d1c8e5267542 Mon Sep 17 00:00:00 2001 From: Mateusz Rzepa Date: Tue, 25 Nov 2025 09:46:23 +0100 Subject: [PATCH] Optimize paging for _ids and facet-only queries --- package-lock.json | 4 +-- package.json | 2 +- src/lib.js | 70 +++++++++++++++++++++++++++++++++-------------- 3 files changed, 52 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5750e80..2a60100 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "itemsjs", - "version": "2.4.3", + "version": "2.4.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "itemsjs", - "version": "2.4.3", + "version": "2.4.4", "license": "Apache-2.0", "devDependencies": { "boolean-parser": "^0.0.2", diff --git a/package.json b/package.json index 84f1f58..7e4b186 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "itemsjs", - "version": "2.4.3", + "version": "2.4.4", "description": "Created to perform fast search on small json dataset (up to 1000 elements).", "type": "module", "scripts": { diff --git a/src/lib.js b/src/lib.js index 2c99efb..f6cbc3f 100644 --- a/src/lib.js +++ b/src/lib.js @@ -89,13 +89,40 @@ export function search(items, input, configuration, fulltext, facets) { ); } - // new filters to items - // ------------------------------------- - let filtered_indexes = filtered_indexes_bitmap.array(); + // Early exit: per_page = 0 and no need to materialize items (facet-only query) + if ( + per_page === 0 && + !is_all_filtered_items && + !input.sort && + !_ids + ) { + const filtered_indexes = filtered_indexes_bitmap.array(); - let filtered_items = filtered_indexes.map((_id) => { - return facets.get_item(_id); - }); + const total_time = new Date().getTime() - total_time_start; + + return { + pagination: { + per_page: per_page, + page: page, + total: filtered_indexes.length, + }, + timings: { + total: total_time, + facets: facets_time, + search: search_time, + sorting: 0, + }, + data: { + items: [], + allFilteredItems: null, + aggregations: getBuckets( + facet_result, + input, + configuration.aggregations, + ), + }, + }; + } /** * sorting items @@ -103,28 +130,29 @@ export function search(items, input, configuration, fulltext, facets) { let paginationApplied = false; const sorting_start_time = new Date().getTime(); let sorting_time = 0; + + // collect ids once; reuse in branches below + let filtered_indexes = filtered_indexes_bitmap.array(); + let filtered_items; + if (input.sort) { + filtered_items = filtered_indexes.map((_id) => facets.get_item(_id)); filtered_items = sorted_items( filtered_items, input.sort, configuration.sortings, ); + } else if (_ids) { + // when user passes explicit ids/_ids we only materialize items for the current page + filtered_indexes = _ids.filter((v) => filtered_indexes_bitmap.has(v)); + const filtered_items_indexes = filtered_indexes.slice( + (page - 1) * per_page, + page * per_page, + ); + filtered_items = filtered_items_indexes.map((_id) => facets.get_item(_id)); + paginationApplied = true; } else { - if (_ids) { - filtered_indexes = _ids.filter((v) => { - return filtered_indexes_bitmap.has(v); - }); - - const filtered_items_indexes = filtered_indexes.slice( - (page - 1) * per_page, - page * per_page, - ); - filtered_items = filtered_items_indexes.map((_id) => { - return facets.get_item(_id); - }); - - paginationApplied = true; - } + filtered_items = filtered_indexes.map((_id) => facets.get_item(_id)); } // pagination if (!paginationApplied) {