[Bug 42835] New: ElasticSearch should have an items index
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Bug ID: 42835 Summary: ElasticSearch should have an items index Initiative type: --- Sponsorship --- status: Product: Koha Version: Main Hardware: All OS: All Status: NEW Severity: normal Priority: P5 - low Component: Searching - Elasticsearch Assignee: koha-bugs@lists.koha-community.org Reporter: pedro.amorim@openfifth.co.uk QA Contact: testopia@bugs.koha-community.org Target Milestone: --- -- You are receiving this mail because: You are watching all bug changes. You are the assignee for the bug.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |Needs Signoff -- You are receiving this mail because: You are watching all bug changes. You are the assignee for the bug.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #1 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200312 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200312&action=edit Bug 42835: Elasticsearch: Add items index Adds a dedicated 'items' Elasticsearch index where each item is its own flat document keyed by itemnumber, built from Koha::Item data rather than MARC. Adds index_items() and delete_items() to Indexer.pm. Hooks into Item::store() and Item::delete() via _update_es_index() to keep the index in sync on every item change; a skip_items_index flag allows bulk operations to bypass it. Items in their own index can be updated on circulation without re-parsing MARC, keeping availability and facet counts accurate in real time. Adds a noop mock for index_items in the Elasticsearch.t test fixture to prevent store() calls inside marc_records_to_documents tests from trying to index items into ES. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes. You are the assignee for the bug.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #2 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200313 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200313&action=edit Bug 42835: Koha::Item: Skip biblio re-index for circulation-only field changes When only fields in %ITEM_CIRC_FIELDS are modified (onloan, issues, renewals, holdingbranch, datelastborrowed, datelastseen, localuse, reserves, timestamp), skip the biblio MARC re-index — the items index is authoritative for this data. notforloan, damaged, itemlost and withdrawn are excluded from the skip set: they affect the available field in the biblios index and must trigger a re-index to keep availability filtering correct. The skip is further gated on _items_index_ready(): the biblio re-index is only skipped when the items index is sufficiently populated (>=95% of DB items indexed). This prevents stale availability data on fresh installs where the items index may contain only a handful of documents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are the assignee for the bug. You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #3 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200314 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200314&action=edit Bug 42835: rebuild_elasticsearch.pl: Add --items flag Adds -i|--items to rebuild the items index from the database (not from MARC). Items are not included in the default "index everything" behaviour and must be requested explicitly. Also adds -in|--itemnumber to reindex one or more specific items. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are the assignee for the bug. You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #4 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200315 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200315&action=edit Bug 42835: Elasticsearch: Route availability and facets through items index Queries the items index for availability filtering and item-level facets (itype, location, ccode, homebranch, holdingbranch). Uses cardinality sub-aggregations for per-biblio facet counts rather than per-item counts. Adds biblionumber as an explicit integer field in the biblios index mapping and stamps it on biblio documents so item facet queries can be scoped to the current search result set via a _biblionumbers aggregation. Fixes a bug where _apply_available_filter assumed available:true was always at must[0]; now scans all must elements. Fixes a bug where biblio_count{value} was tested for hashref truthiness rather than key existence, always preferring it over doc_count. Fixes the biblios index available field to correctly treat notforloan, damaged, and withdrawn items as unavailable — previously only onloan and itemlost were checked. Covers both item-level notforloan and items whose item type has notforloan set. Updates existing tests in Elasticsearch.t that were asserting the previous wrong behaviour. Items index routing is unconditional here; the readiness gate that prevents empty-index regressions on upgrade is added in the next commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes. You are the assignee for the bug.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #5 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200316 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200316&action=edit Bug 42835: OPAC performance: Batch item visibility check to reduce N+1 DB queries Before the main result loop, pre-scan all MARC records for the current page to collect every itemnumber in one pass. Run a single batched filter_by_visible_in_opac call and store the result in a hash. The inner item loop then does a plain hash lookup instead of one Koha::Items DB query per item, reducing N queries to 1 per page load. Falls back to the per-item path if no itemnumbers are found in the pre-scan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are the assignee for the bug. You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #6 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200317 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200317&action=edit Bug 42835: Elasticsearch: Gate items index features behind readiness check Adds _items_index_ready() which checks whether the items index is fully populated before enabling availability filtering and facet aggregation. The index is considered ready only when it contains at least 95% of the items in the database — this prevents the gate opening after a single circulation event has indexed one item before rebuild_elasticsearch.pl --items has been run. The result is cached: 5 minutes when ready, 60 seconds when not, so a freshly populated index is detected quickly without a restart. TEST PLAN (Do not apply patches yet) 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you get 40 results. 9 of these bibs have all their items unavailable and should NOT be showing. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. 9) Let's pick a 2nd bib from that same search ('music' + only available): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 10) Edit that single item, put it 'Not for loan' 11) Refresh the search. Notice the bib is always showing, even though all its items are unavailable (This is incorrect): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available APPLY PATCHES 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you now get 31 results. The previous 9 with all their items unavailable do not show anymore. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is still correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. This is still the case because a full reindex (to create the items index) has not occurred yet. Let's do that 9) Run: $ perl misc/search_tools/rebuild_elasticsearch.pl -i -r -v 10) Do another check-out for a 2nd bib with a single item e.g. (39999000016710): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 11) Check the background jobs again: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 12) Notice a new full bib record reindex job was not triggered, because this was updated directly on the items index synchronously. Confirm that bib record no longer shows on the 'only available' search: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available 13) Pick a third bib from the same search http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=374 14) Edit the single item and put it 'not for loan'. 15) Refresh the search. Notice the bib is not showing anymore, because all its items are unavailable (This is now correct): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available Benefits: 1. notforloan/damaged/withdrawn availability fix 2. Skip biblio re-index on checkout — performance improvement, visible under load 3. Availability filtering via items index — real-time post-checkout 4. Safe on upgrade — falls back to the biblios index until a rebuild with --items is run, no hard requirement to rebuild before the system works correctly. Run tests: prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Search.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Indexer.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch.t prove t/db_dependent/Koha/Item.t prove t/db_dependent/Search.t prove t/db_dependent/Koha/SearchEngine/Search.t Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes. You are the assignee for the bug.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 David Nind <david@davidnind.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |david@davidnind.com Assignee|koha-bugs@lists.koha-commun |pedro.amorim@openfifth.co.u |ity.org |k --- Comment #7 from David Nind <david@davidnind.com> --- Added assignee 8-) -- You are receiving this mail because: You are watching all bug changes. You are the assignee for the bug.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |pedro.amorim@openfifth.co.u | |k Status|Needs Signoff |Patch doesn't apply -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Patch doesn't apply |Needs Signoff -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #200312|0 |1 is obsolete| | Attachment #200313|0 |1 is obsolete| | Attachment #200314|0 |1 is obsolete| | Attachment #200315|0 |1 is obsolete| | Attachment #200316|0 |1 is obsolete| | Attachment #200317|0 |1 is obsolete| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #8 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200605 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200605&action=edit Bug 42835: Elasticsearch: Add items index Adds a dedicated 'items' Elasticsearch index where each item is its own flat document keyed by itemnumber, built from Koha::Item data rather than MARC. Adds index_items() and delete_items() to Indexer.pm. Hooks into Item::store() and Item::delete() via _update_es_index() to keep the index in sync on every item change; a skip_items_index flag allows bulk operations to bypass it. Items in their own index can be updated on circulation without re-parsing MARC, keeping availability and facet counts accurate in real time. Adds a noop mock for index_items in the Elasticsearch.t test fixture to prevent store() calls inside marc_records_to_documents tests from trying to index items into ES. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #9 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200606 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200606&action=edit Bug 42835: Koha::Item: Skip biblio re-index for circulation-only field changes When only fields in %ITEM_CIRC_FIELDS are modified (onloan, issues, renewals, holdingbranch, datelastborrowed, datelastseen, localuse, reserves, timestamp), skip the biblio MARC re-index — the items index is authoritative for this data. notforloan, damaged, itemlost and withdrawn are excluded from the skip set: they affect the available field in the biblios index and must trigger a re-index to keep availability filtering correct. The skip is further gated on _items_index_ready(): the biblio re-index is only skipped when the items index is sufficiently populated (>=95% of DB items indexed). This prevents stale availability data on fresh installs where the items index may contain only a handful of documents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #10 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200607 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200607&action=edit Bug 42835: rebuild_elasticsearch.pl: Add --items flag Adds -i|--items to rebuild the items index from the database (not from MARC). Items are not included in the default "index everything" behaviour and must be requested explicitly. Also adds -in|--itemnumber to reindex one or more specific items. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #11 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200608 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200608&action=edit Bug 42835: Elasticsearch: Route availability and facets through items index Queries the items index for availability filtering and item-level facets (itype, location, ccode, homebranch, holdingbranch). Uses cardinality sub-aggregations for per-biblio facet counts rather than per-item counts. Adds biblionumber as an explicit integer field in the biblios index mapping and stamps it on biblio documents so item facet queries can be scoped to the current search result set via a _biblionumbers aggregation. Fixes a bug where _apply_available_filter assumed available:true was always at must[0]; now scans all must elements. Fixes a bug where biblio_count{value} was tested for hashref truthiness rather than key existence, always preferring it over doc_count. Fixes the biblios index available field to correctly treat notforloan, damaged, and withdrawn items as unavailable — previously only onloan and itemlost were checked. Covers both item-level notforloan and items whose item type has notforloan set. Updates existing tests in Elasticsearch.t that were asserting the previous wrong behaviour. Items index routing is unconditional here; the readiness gate that prevents empty-index regressions on upgrade is added in the next commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #12 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200609 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200609&action=edit Bug 42835: OPAC performance: Batch item visibility check to reduce N+1 DB queries Before the main result loop, pre-scan all MARC records for the current page to collect every itemnumber in one pass. Run a single batched filter_by_visible_in_opac call and store the result in a hash. The inner item loop then does a plain hash lookup instead of one Koha::Items DB query per item, reducing N queries to 1 per page load. Falls back to the per-item path if no itemnumbers are found in the pre-scan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #13 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 200610 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200610&action=edit Bug 42835: Elasticsearch: Gate items index features behind readiness check Adds _items_index_ready() which checks whether the items index is fully populated before enabling availability filtering and facet aggregation. The index is considered ready only when it contains at least 95% of the items in the database — this prevents the gate opening after a single circulation event has indexed one item before rebuild_elasticsearch.pl --items has been run. The result is cached: 5 minutes when ready, 60 seconds when not, so a freshly populated index is detected quickly without a restart. TEST PLAN (Do not apply patches yet) 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you get 40 results. 9 of these bibs have all their items unavailable and should NOT be showing. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. 9) Let's pick a 2nd bib from that same search ('music' + only available): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 10) Edit that single item, put it 'Not for loan' 11) Refresh the search. Notice the bib is always showing, even though all its items are unavailable (This is incorrect): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available APPLY PATCHES 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you now get 31 results. The previous 9 with all their items unavailable do not show anymore. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is still correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. This is still the case because a full reindex (to create the items index) has not occurred yet. Let's do that 9) Run: $ perl misc/search_tools/rebuild_elasticsearch.pl -i -r -v 10) Do another check-out for a 2nd bib with a single item e.g. (39999000016710): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 11) Check the background jobs again: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 12) Notice a new full bib record reindex job was not triggered, because this was updated directly on the items index synchronously. Confirm that bib record no longer shows on the 'only available' search: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available 13) Pick a third bib from the same search http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=374 14) Edit the single item and put it 'not for loan'. 15) Refresh the search. Notice the bib is not showing anymore, because all its items are unavailable (This is now correct): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available Benefits: 1. notforloan/damaged/withdrawn availability fix 2. Skip biblio re-index on checkout — performance improvement, visible under load 3. Availability filtering via items index — real-time post-checkout 4. Safe on upgrade — falls back to the biblios index until a rebuild with --items is run, no hard requirement to rebuild before the system works correctly. Run tests: prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Search.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Indexer.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch.t prove t/db_dependent/Koha/Item.t prove t/db_dependent/Search.t prove t/db_dependent/Koha/SearchEngine/Search.t Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |andrew@bywatersolutions.com | |, | |martin.renvoize@openfifth.c | |o.uk, | |nick@bywatersolutions.com -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |42643 Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42643 [Bug 42643] [OMNIBUS] Assorted performance and stability work -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |42958 Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42958 [Bug 42958] Expand Elasticsearch/Opensearch usage across Koha beyond bibliographic search -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Strategic theme|--- |Performance Target Milestone|--- |26.11 Initiative type|--- |Epic -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Initiative type|Epic |Feature -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks|42643 | Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42643 [Bug 42643] [OMNIBUS] Assorted performance and stability work -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 David Nind <david@davidnind.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Needs Signoff |Signed Off -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 David Nind <david@davidnind.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #200605|0 |1 is obsolete| | Attachment #200606|0 |1 is obsolete| | Attachment #200607|0 |1 is obsolete| | Attachment #200608|0 |1 is obsolete| | Attachment #200609|0 |1 is obsolete| | Attachment #200610|0 |1 is obsolete| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #14 from David Nind <david@davidnind.com> --- Created attachment 202138 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202138&action=edit Bug 42835: Elasticsearch: Add items index Adds a dedicated 'items' Elasticsearch index where each item is its own flat document keyed by itemnumber, built from Koha::Item data rather than MARC. Adds index_items() and delete_items() to Indexer.pm. Hooks into Item::store() and Item::delete() via _update_es_index() to keep the index in sync on every item change; a skip_items_index flag allows bulk operations to bypass it. Items in their own index can be updated on circulation without re-parsing MARC, keeping availability and facet counts accurate in real time. Adds a noop mock for index_items in the Elasticsearch.t test fixture to prevent store() calls inside marc_records_to_documents tests from trying to index items into ES. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #15 from David Nind <david@davidnind.com> --- Created attachment 202139 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202139&action=edit Bug 42835: Koha::Item: Skip biblio re-index for circulation-only field changes When only fields in %ITEM_CIRC_FIELDS are modified (onloan, issues, renewals, holdingbranch, datelastborrowed, datelastseen, localuse, reserves, timestamp), skip the biblio MARC re-index — the items index is authoritative for this data. notforloan, damaged, itemlost and withdrawn are excluded from the skip set: they affect the available field in the biblios index and must trigger a re-index to keep availability filtering correct. The skip is further gated on _items_index_ready(): the biblio re-index is only skipped when the items index is sufficiently populated (>=95% of DB items indexed). This prevents stale availability data on fresh installs where the items index may contain only a handful of documents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #16 from David Nind <david@davidnind.com> --- Created attachment 202140 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202140&action=edit Bug 42835: rebuild_elasticsearch.pl: Add --items flag Adds -i|--items to rebuild the items index from the database (not from MARC). Items are not included in the default "index everything" behaviour and must be requested explicitly. Also adds -in|--itemnumber to reindex one or more specific items. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #17 from David Nind <david@davidnind.com> --- Created attachment 202141 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202141&action=edit Bug 42835: Elasticsearch: Route availability and facets through items index Queries the items index for availability filtering and item-level facets (itype, location, ccode, homebranch, holdingbranch). Uses cardinality sub-aggregations for per-biblio facet counts rather than per-item counts. Adds biblionumber as an explicit integer field in the biblios index mapping and stamps it on biblio documents so item facet queries can be scoped to the current search result set via a _biblionumbers aggregation. Fixes a bug where _apply_available_filter assumed available:true was always at must[0]; now scans all must elements. Fixes a bug where biblio_count{value} was tested for hashref truthiness rather than key existence, always preferring it over doc_count. Fixes the biblios index available field to correctly treat notforloan, damaged, and withdrawn items as unavailable — previously only onloan and itemlost were checked. Covers both item-level notforloan and items whose item type has notforloan set. Updates existing tests in Elasticsearch.t that were asserting the previous wrong behaviour. Items index routing is unconditional here; the readiness gate that prevents empty-index regressions on upgrade is added in the next commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #18 from David Nind <david@davidnind.com> --- Created attachment 202142 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202142&action=edit Bug 42835: OPAC performance: Batch item visibility check to reduce N+1 DB queries Before the main result loop, pre-scan all MARC records for the current page to collect every itemnumber in one pass. Run a single batched filter_by_visible_in_opac call and store the result in a hash. The inner item loop then does a plain hash lookup instead of one Koha::Items DB query per item, reducing N queries to 1 per page load. Falls back to the per-item path if no itemnumbers are found in the pre-scan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #19 from David Nind <david@davidnind.com> --- Created attachment 202143 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202143&action=edit Bug 42835: Elasticsearch: Gate items index features behind readiness check Adds _items_index_ready() which checks whether the items index is fully populated before enabling availability filtering and facet aggregation. The index is considered ready only when it contains at least 95% of the items in the database — this prevents the gate opening after a single circulation event has indexed one item before rebuild_elasticsearch.pl --items has been run. The result is cached: 5 minutes when ready, 60 seconds when not, so a freshly populated index is detected quickly without a restart. TEST PLAN (Do not apply patches yet) 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you get 40 results. 9 of these bibs have all their items unavailable and should NOT be showing. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. 9) Let's pick a 2nd bib from that same search ('music' + only available): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 10) Edit that single item, put it 'Not for loan' 11) Refresh the search. Notice the bib is always showing, even though all its items are unavailable (This is incorrect): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available APPLY PATCHES 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you now get 31 results. The previous 9 with all their items unavailable do not show anymore. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is still correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. This is still the case because a full reindex (to create the items index) has not occurred yet. Let's do that 9) Run: $ perl misc/search_tools/rebuild_elasticsearch.pl -i -r -v 10) Do another check-out for a 2nd bib with a single item e.g. (39999000016710): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 11) Check the background jobs again: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 12) Notice a new full bib record reindex job was not triggered, because this was updated directly on the items index synchronously. Confirm that bib record no longer shows on the 'only available' search: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available 13) Pick a third bib from the same search http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=374 14) Edit the single item and put it 'not for loan'. 15) Refresh the search. Notice the bib is not showing anymore, because all its items are unavailable (This is now correct): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available Benefits: 1. notforloan/damaged/withdrawn availability fix 2. Skip biblio re-index on checkout — performance improvement, visible under load 3. Availability filtering via items index — real-time post-checkout 4. Safe on upgrade — falls back to the biblios index until a rebuild with --items is run, no hard requirement to rebuild before the system works correctly. Run tests: prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Search.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Indexer.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch.t prove t/db_dependent/Koha/Item.t prove t/db_dependent/Search.t prove t/db_dependent/Koha/SearchEngine/Search.t Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 David Nind <david@davidnind.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |release-notes-needed --- Comment #20 from David Nind <david@davidnind.com> --- Testing notes (using KTD): 1. Tested using Elasticsearch 9: ktd --search-engine es9 up -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Signed Off |Patch doesn't apply -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Patch doesn't apply |Signed Off -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #202138|0 |1 is obsolete| | Attachment #202139|0 |1 is obsolete| | Attachment #202140|0 |1 is obsolete| | Attachment #202141|0 |1 is obsolete| | Attachment #202142|0 |1 is obsolete| | Attachment #202143|0 |1 is obsolete| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #21 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202229 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202229&action=edit Bug 42835: Elasticsearch: Add items index Adds a dedicated 'items' Elasticsearch index where each item is its own flat document keyed by itemnumber, built from Koha::Item data rather than MARC. Adds index_items() and delete_items() to Indexer.pm. Hooks into Item::store() and Item::delete() via _update_es_index() to keep the index in sync on every item change; a skip_items_index flag allows bulk operations to bypass it. Items in their own index can be updated on circulation without re-parsing MARC, keeping availability and facet counts accurate in real time. Adds a noop mock for index_items in the Elasticsearch.t test fixture to prevent store() calls inside marc_records_to_documents tests from trying to index items into ES. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #22 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202230 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202230&action=edit Bug 42835: Koha::Item: Skip biblio re-index for circulation-only field changes When only fields in %ITEM_CIRC_FIELDS are modified (onloan, issues, renewals, holdingbranch, datelastborrowed, datelastseen, localuse, reserves, timestamp), skip the biblio MARC re-index — the items index is authoritative for this data. notforloan, damaged, itemlost and withdrawn are excluded from the skip set: they affect the available field in the biblios index and must trigger a re-index to keep availability filtering correct. The skip is further gated on _items_index_ready(): the biblio re-index is only skipped when the items index is sufficiently populated (>=95% of DB items indexed). This prevents stale availability data on fresh installs where the items index may contain only a handful of documents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #23 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202231 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202231&action=edit Bug 42835: rebuild_elasticsearch.pl: Add --items flag Adds -i|--items to rebuild the items index from the database (not from MARC). Items are not included in the default "index everything" behaviour and must be requested explicitly. Also adds -in|--itemnumber to reindex one or more specific items. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #24 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202232 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202232&action=edit Bug 42835: Elasticsearch: Route availability and facets through items index Queries the items index for availability filtering and item-level facets (itype, location, ccode, homebranch, holdingbranch). Uses cardinality sub-aggregations for per-biblio facet counts rather than per-item counts. Adds biblionumber as an explicit integer field in the biblios index mapping and stamps it on biblio documents so item facet queries can be scoped to the current search result set via a _biblionumbers aggregation. Fixes a bug where _apply_available_filter assumed available:true was always at must[0]; now scans all must elements. Fixes a bug where biblio_count{value} was tested for hashref truthiness rather than key existence, always preferring it over doc_count. Fixes the biblios index available field to correctly treat notforloan, damaged, and withdrawn items as unavailable — previously only onloan and itemlost were checked. Covers both item-level notforloan and items whose item type has notforloan set. Updates existing tests in Elasticsearch.t that were asserting the previous wrong behaviour. Items index routing is unconditional here; the readiness gate that prevents empty-index regressions on upgrade is added in the next commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #25 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202233 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202233&action=edit Bug 42835: OPAC performance: Batch item visibility check to reduce N+1 DB queries Before the main result loop, pre-scan all MARC records for the current page to collect every itemnumber in one pass. Run a single batched filter_by_visible_in_opac call and store the result in a hash. The inner item loop then does a plain hash lookup instead of one Koha::Items DB query per item, reducing N queries to 1 per page load. Falls back to the per-item path if no itemnumbers are found in the pre-scan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #26 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202234 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202234&action=edit Bug 42835: Elasticsearch: Gate items index features behind readiness check Adds _items_index_ready() which checks whether the items index is fully populated before enabling availability filtering and facet aggregation. The index is considered ready only when it contains at least 95% of the items in the database — this prevents the gate opening after a single circulation event has indexed one item before rebuild_elasticsearch.pl --items has been run. The result is cached: 5 minutes when ready, 60 seconds when not, so a freshly populated index is detected quickly without a restart. TEST PLAN (Do not apply patches yet) 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you get 40 results. 9 of these bibs have all their items unavailable and should NOT be showing. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. 9) Let's pick a 2nd bib from that same search ('music' + only available): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 10) Edit that single item, put it 'Not for loan' 11) Refresh the search. Notice the bib is always showing, even though all its items are unavailable (This is incorrect): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available APPLY PATCHES 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you now get 31 results. The previous 9 with all their items unavailable do not show anymore. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is still correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. This is still the case because a full reindex (to create the items index) has not occurred yet. Let's do that 9) Run: $ perl misc/search_tools/rebuild_elasticsearch.pl -i -r -v 10) Do another check-out for a 2nd bib with a single item e.g. (39999000016710): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 11) Check the background jobs again: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 12) Notice a new full bib record reindex job was not triggered, because this was updated directly on the items index synchronously. Confirm that bib record no longer shows on the 'only available' search: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available 13) Pick a third bib from the same search http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=374 14) Edit the single item and put it 'not for loan'. 15) Refresh the search. Notice the bib is not showing anymore, because all its items are unavailable (This is now correct): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available Benefits: 1. notforloan/damaged/withdrawn availability fix 2. Skip biblio re-index on checkout — performance improvement, visible under load 3. Availability filtering via items index — real-time post-checkout 4. Safe on upgrade — falls back to the biblios index until a rebuild with --items is run, no hard requirement to rebuild before the system works correctly. Run tests: prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Search.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Indexer.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch.t prove t/db_dependent/Koha/Item.t prove t/db_dependent/Search.t prove t/db_dependent/Koha/SearchEngine/Search.t Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Andrew Fuerste-Henry <andrew@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |43151 Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43151 [Bug 43151] ES should apply search filters on each item discretely -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #202229|0 |1 is obsolete| | Attachment #202230|0 |1 is obsolete| | Attachment #202231|0 |1 is obsolete| | Attachment #202232|0 |1 is obsolete| | Attachment #202233|0 |1 is obsolete| | Attachment #202234|0 |1 is obsolete| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #27 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202480 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202480&action=edit Bug 42835: Elasticsearch: Add items index Adds a dedicated 'items' Elasticsearch index where each item is its own flat document keyed by itemnumber, built from Koha::Item data rather than MARC. Adds index_items() and delete_items() to Indexer.pm. Hooks into Item::store() and Item::delete() via _update_es_index() to keep the index in sync on every item change; a skip_items_index flag allows bulk operations to bypass it. Items in their own index can be updated on circulation without re-parsing MARC, keeping availability and facet counts accurate in real time. Adds a noop mock for index_items in the Elasticsearch.t test fixture to prevent store() calls inside marc_records_to_documents tests from trying to index items into ES. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #28 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202481 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202481&action=edit Bug 42835: Koha::Item: Skip biblio re-index for circulation-only field changes When only fields in %ITEM_CIRC_FIELDS are modified (onloan, issues, renewals, holdingbranch, datelastborrowed, datelastseen, localuse, reserves, timestamp), skip the biblio MARC re-index — the items index is authoritative for this data. notforloan, damaged, itemlost and withdrawn are excluded from the skip set: they affect the available field in the biblios index and must trigger a re-index to keep availability filtering correct. The skip is further gated on _items_index_ready(): the biblio re-index is only skipped when the items index is sufficiently populated (>=95% of DB items indexed). This prevents stale availability data on fresh installs where the items index may contain only a handful of documents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #29 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202482 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202482&action=edit Bug 42835: rebuild_elasticsearch.pl: Add --items flag Adds -i|--items to rebuild the items index from the database (not from MARC). Items are not included in the default "index everything" behaviour and must be requested explicitly. Also adds -in|--itemnumber to reindex one or more specific items. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #30 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202483 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202483&action=edit Bug 42835: Elasticsearch: Route availability and facets through items index Queries the items index for availability filtering and item-level facets (itype, location, ccode, homebranch, holdingbranch). Uses cardinality sub-aggregations for per-biblio facet counts rather than per-item counts. Adds biblionumber as an explicit integer field in the biblios index mapping and stamps it on biblio documents so item facet queries can be scoped to the current search result set via a _biblionumbers aggregation. Fixes a bug where _apply_available_filter assumed available:true was always at must[0]; now scans all must elements. Fixes a bug where biblio_count{value} was tested for hashref truthiness rather than key existence, always preferring it over doc_count. Fixes the biblios index available field to correctly treat notforloan, damaged, and withdrawn items as unavailable — previously only onloan and itemlost were checked. Covers both item-level notforloan and items whose item type has notforloan set. Updates existing tests in Elasticsearch.t that were asserting the previous wrong behaviour. Items index routing is unconditional here; the readiness gate that prevents empty-index regressions on upgrade is added in the next commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #31 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202484 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202484&action=edit Bug 42835: OPAC performance: Batch item visibility check to reduce N+1 DB queries Before the main result loop, pre-scan all MARC records for the current page to collect every itemnumber in one pass. Run a single batched filter_by_visible_in_opac call and store the result in a hash. The inner item loop then does a plain hash lookup instead of one Koha::Items DB query per item, reducing N queries to 1 per page load. Falls back to the per-item path if no itemnumbers are found in the pre-scan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #32 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202485 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202485&action=edit Bug 42835: Elasticsearch: Gate items index features behind readiness check Adds _items_index_ready() which checks whether the items index is fully populated before enabling availability filtering and facet aggregation. The index is considered ready only when it contains at least 95% of the items in the database — this prevents the gate opening after a single circulation event has indexed one item before rebuild_elasticsearch.pl --items has been run. The result is cached: 5 minutes when ready, 60 seconds when not, so a freshly populated index is detected quickly without a restart. TEST PLAN (Do not apply patches yet) 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you get 40 results. 9 of these bibs have all their items unavailable and should NOT be showing. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. 9) Let's pick a 2nd bib from that same search ('music' + only available): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 10) Edit that single item, put it 'Not for loan' 11) Refresh the search. Notice the bib is always showing, even though all its items are unavailable (This is incorrect): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available APPLY PATCHES 1) Set up KTD with Elasticsearch 8: ktd --search-engine es8 up 2) Do a search for 'music', you should get 42 results: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music 3) Click the 'Limit to records with available items' facet link. Notice you now get 31 results. The previous 9 with all their items unavailable do not show anymore. 4) Find a biblio with a single item (the top result of the search): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=437 5) Check-out that item (39999000019186) to a patron 6) Repeat the same search with 'Limit to records with available items'. Notice the biblio above is no longer showing (this is still correct). 7) Check the background jobs: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 8) Confirm at least 1 'Update Elasticsearch index' entry exists. This is because a full bib reindex is triggered for anytime a check-out happens. This is still the case because a full reindex (to create the items index) has not occurred yet. Let's do that 9) Run: $ perl misc/search_tools/rebuild_elasticsearch.pl -i -r -v 10) Do another check-out for a 2nd bib with a single item e.g. (39999000016710): http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=380 11) Check the background jobs again: http://localhost:8081/cgi-bin/koha/admin/background_jobs.pl 12) Notice a new full bib record reindex job was not triggered, because this was updated directly on the items index synchronously. Confirm that bib record no longer shows on the 'only available' search: http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available 13) Pick a third bib from the same search http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=374 14) Edit the single item and put it 'not for loan'. 15) Refresh the search. Notice the bib is not showing anymore, because all its items are unavailable (This is now correct): http://localhost:8081/cgi-bin/koha/catalogue/search.pl?idx=&q=music&weight_search=1&sort_by=relevance&limit=available Benefits: 1. notforloan/damaged/withdrawn availability fix 2. Skip biblio re-index on checkout — performance improvement, visible under load 3. Availability filtering via items index — real-time post-checkout 4. Safe on upgrade — falls back to the biblios index until a rebuild with --items is run, no hard requirement to rebuild before the system works correctly. Run tests: prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Search.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Indexer.t prove t/db_dependent/Koha/SearchEngine/Elasticsearch.t prove t/db_dependent/Koha/Item.t prove t/db_dependent/Search.t prove t/db_dependent/Koha/SearchEngine/Search.t Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #33 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202486 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202486&action=edit Bug 42835: (follow-up) Cache items index queries for availability and facets _get_available_biblionumbers() and _get_item_facets() hit the items index on every search, unscoped and uncached. Fine on a small catalog, brutal at real scale - hundreds of round-trips per "available" search. Cache both for 15s. Single key for availability (same result for everyone); MD5-of-biblionumbers key for facets (result is per-search). Test plan: 1) prove t/db_dependent/Koha/SearchEngine/Elasticsearch/Search.t 2) Run demo_cache_fix.pl - second call to each function should be near-instant vs the first Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #34 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Created attachment 202487 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=202487&action=edit Bug 42835: [DO NOT PUSH]: demo script for items index caching fix Standalone script demonstrating the caching fix in the previous commit. Wraps the real ES client to count calls, then calls _get_available_biblionumbers() and _get_item_facets() twice each against a live KTD Elasticsearch instance - first call should hit ES, second should be near-instant from cache. Run: perl demo_cache_fix.pl This commit is for local testing only and must not be pushed upstream. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 --- Comment #35 from Pedro Amorim (ammopt) <pedro.amorim@openfifth.co.uk> --- Squashed in a fix restoring the Try::Tiny import to Koha/Item.pm, removed by bug 42391. Added caching to items index queries for availability and facets. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Andrew Fuerste-Henry <andrew@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Sponsorship status|--- |Sponsored Comma delimited| |Cuyahoga County Public list of Sponsors| |Library -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Lisette Scheer <lisette@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- QA Contact|testopia@bugs.koha-communit |Laura.escamilla@bywatersolu |y.org |tions.com CC| |lisette@bywatersolutions.co | |m -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |35052 Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=35052 [Bug 35052] OpacHiddenItemsHidesRecord system preference should be considered on index time instead -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42835 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Signed Off |Failed QA --- Comment #36 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Some things coming out of a QA review: 1. misc/search_tools/rebuild_elasticsearch.pl:269-271, _do_reindex_items — the new --items path isn't slice-aware. Biblios/authorities reindexing forks --processes N workers and gives each a slice => {index, count} so the table is partitioned across them. _do_reindex_items ignores %iterator_options entirely and does Koha::Items->search({}) unconditionally — every forked worker (not just the parent) reindexes the entire items table independently. Still correct (idempotent by itemnumber), but on a large catalog --items --processes 4 does 4x the ES writes and DB scans instead of dividing the work, defeating the point of --processes. 2. Koha/Item.pm:73-78 (%ITEM_CIRC_FIELDS) — holdingbranch is deliberately in the "skip biblio reindex" set (per the commit message: "AddIssue always sets it alongside onloan"), so ordinary checkouts still qualify for the fast path. But that means a genuine branch transfer (also just a holdingbranch change) skips the biblio reindex too. The items-index facets stay correct (they're queried live), but the ES-stored MARC blob used to render search-result rows (branch/location shown per hit) goes stale until some unrelated reindex trigger fires. Net effect: after a transfer, the facet count and the actual result-row "held at" branch can disagree. 3. No test coverage for the actual N+1 fix — C4/Search.pm's new pre-scan/batched visibility check (searchResults() ~1740-1765, ~1895-1905) has no corresponding change in t/db_dependent/Search.t. Every other piece of this patchset (readiness gate, caching, items index CRUD) has solid test coverage confirmed by direct reading; this is the one production change that ships untested — worth a test with a mixed visible/hidden batch, an empty batch, and the fallback-to-per-item path. And, some possible nice to haves: 1. C4/Search.pm:1750/1752 vs 1774/1778 — the visibility pre-scan parses every page's MARC record with MARC::Record->new_from_usmarc/new_record_from_zebra, then the main loop parses the same record again. Cheap relative to the DB round-trips saved, but stashing the already-parsed record from the pre-scan and reusing it would remove the duplicate work entirely. 2. Koha/SearchEngine/Elasticsearch.pm — adds Readonly our $ITEMS_INDEX => 'items'; locally even though the file now also does use Koha::SearchEngine;, which defines the same constant. Matches the file's pre-existing (already duplicated) $BIBLIOS_INDEX/$AUTHORITIES_INDEX pattern, so not new, but a third duplicate constant is a good excuse to collapse to one source of truth. 3. POD is thin on Koha::Item::_update_es_index and Koha::SearchEngine::Elasticsearch::Indexer::_item_to_document (headers present, no real description). 4. Search.pm:search_compat now always adds a _biblionumbers terms aggregation (size => 9_000) plus a second ES round-trip to the items index for facets, on every biblios-index search once the items index is ready — even for callers that don't use the returned facets. Not a bug, but worth confirming it doesn't add measurable per-search latency on large result sets. -- You are receiving this mail because: You are watching all bug changes.
participants (1)
-
bugzilla-daemon@bugs.koha-community.org