Back-fill the Lucene index when registered on a populated GigaMap - #718
Merged
Conversation
A Lucene full-text index registered on a GigaMap that already held entities only indexed entities added afterwards — pre-existing ones were invisible to search. Bitmap and JVector indices already back-fill on registration; this aligns Lucene with that behavior. Add a default no-op internalOnRegistered() lifecycle hook to IndexGroup.Internal, invoked by GigaIndices.register after a group is added (and not on deserialization, which reconstructs groups via their binary handlers). LuceneIndex overrides it to index all existing entities via iterateIndexed, using the real GigaMap entity ids so later update/remove keep working, adding documents incrementally and committing once (honoring autoCommit, skipping an empty commit). Other groups inherit the no-op, so registering the empty VectorIndices container does not trigger a wasted full-map scan. This also covers the annotation path (@fulltext / LuceneAnnotationHandler), which funnels through the same register call. Add LuceneBackfillTest (basic back-fill, empty map, id correctness on update/remove, persistence round-trip without double-indexing, manual-commit context) and document the behavior in the Lucene index and annotation pages.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a correctness gap where a Lucene full-text index registered on an already-populated GigaMap would only index entities added after registration, by adding a post-registration lifecycle hook and using it to back-fill existing entities into the Lucene index. It also adds tests and documentation updates to cover and explain the new behavior.
Changes:
- Add
IndexGroup.Internal#internalOnRegistered()(default no-op) and invoke it after successful group registration. - Implement Lucene back-fill on registration via
iterateIndexed, and refactor document creation into a sharedtoDocument(...)helper. - Add
LuceneBackfillTestand update Lucene indexing docs to state that registration on populated maps back-fills existing entities.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| gigamap/lucene/src/test/java/org/eclipse/store/gigamap/lucene/LuceneBackfillTest.java | New tests validating Lucene back-fill behavior, id correctness for update/remove, and persistence/manual-commit scenarios. |
| gigamap/lucene/src/main/java/org/eclipse/store/gigamap/lucene/LuceneIndex.java | Adds Lucene back-fill on registration and centralizes document construction in toDocument(...). |
| gigamap/gigamap/src/main/java/org/eclipse/store/gigamap/types/IndexGroup.java | Introduces the internalOnRegistered() lifecycle hook (default no-op) for index groups. |
| gigamap/gigamap/src/main/java/org/eclipse/store/gigamap/types/GigaIndices.java | Calls internalOnRegistered() immediately after registering a new index group. |
| docs/modules/gigamap/pages/indexing/lucene/index.adoc | Documents that registering Lucene on a populated map back-fills existing entities and may require a one-time scan. |
| docs/modules/gigamap/pages/indexing/lucene/defining.adoc | Documents that annotation-generated Lucene indices are also back-filled when generated on populated maps. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- GigaIndices.register: make registration atomic — roll back (remove + close) the group if internalOnRegistered() throws, and mark state change only on success. - LuceneIndex: reword the back-fill comment — autoCommit==false defers durability, not search visibility (the NRT reader stays queryable). - LuceneBackfillTest: drop unused List import; add a rollback test.
zdenek-jonas
approved these changes
Jun 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A Lucene full-text index registered on a
GigaMapthat already contained entities only indexed entities added after registration — pre-existing entities were silently invisible to full-text search. The bitmap and JVector indices already back-fill from existing entities on registration; Lucene did not, which is both an inconsistency and a silent correctness gap (queries miss data).This also affected the annotation-driven path (
@FullText/LuceneAnnotationHandler/IndexerGenerator.generateIndices), which is user-callable on a populated map.Change
internalOnRegistered()toIndexGroup.Internal, invoked byGigaIndices.register(...)immediately after a group is added. It is not called on deserialization (groups are reconstructed via their binary handlers), so there is no re-indexing / double-indexing on restart.LuceneIndexoverrides the hook to index all existing entities viaiterateIndexed, using the real GigaMap-assigned entity ids (so laterupdate/remove, which look up by id, keep working). Documents are added incrementally and committed once at the end, honoring theautoCommitcontract and skipping an empty commit on an empty map.VectorIndicescontainer does not trigger a wasteful full-map scan; its existing per-index back-fill is unchanged.toDocument(entityId, entity)helper, now the single document-construction point used byinternalAdd,internalAddAll,internalUpdateIndices, and the back-fill.Registration order no longer matters: an index can be added before or after data is loaded.
Why a hook (not a generic back-fill in
register)A generic
iterateIndexedinregisterwould force a full-map scan (loading everyLazysegment) just to register the emptyVectorIndicescontainer. Doing it increateIndexGroupwould scan the map even for a discarded duplicate group (the already-registered check runs after creation). The hook lets each group opt in; only Lucene needs it.Tests
New
LuceneBackfillTest:update/removeautoCommit=false) contextAll module suites pass:
gigamap(1034),lucene(58),jvector(189).Docs
Updated the Lucene index and annotation pages to state that registering on a populated GigaMap back-fills existing entities, with a note about the one-time full-entity scan on very large maps.