Skip to content

feat(fts): honor per-field searchable flag#58

Merged
bigin merged 1 commit into
mainfrom
feat/searchable-honored
May 17, 2026
Merged

feat(fts): honor per-field searchable flag#58
bigin merged 1 commit into
mainfrom
feat/searchable-honored

Conversation

@bigin

@bigin bigin commented May 17, 2026

Copy link
Copy Markdown
Owner

SqliteItemRepository::syncFts() now consults the FieldRepository for the per-category set of searchable: true field names and filters the items_fts.body write accordingly. FullTextSearch:: rebuild() does the same in a single pre-pass over the fields table plus per-item iteration.

Migration 0005_searchable_defaults.sql preserves existing FTS coverage on upgrade by promoting all text/longtext/editor/slug field rows to searchable=1 (matches the 2.2.0 factory defaults). Verified against a copy of the live Scriptor schema: all 8 text-typed fields promote; password + fileupload stay at 0.

Backward compatibility: SqliteItemRepository's third constructor arg (?FieldRepository) is optional. The 2.0/2.1 two-arg signature keeps working — falls back to "index everything" with a one-time E_USER_DEPRECATED notice on first FTS write.

Body composition extracted to FtsBody::compose() so the per-save writer and the bulk rebuilder cannot drift on the format. The plan called for per-process category-fields caching with event- based invalidation; revisited and dropped: per-save fetch from local SQLite is sub-millisecond, and the no-cache path can't go stale in long-running CLI processes.

New test file SearchableFlagTest covers: opt-out per save, structural name+label always indexed, update refreshes set, rebuild respects flag, per-category isolation, flip-then-rebuild contract, migration 0005 row-level effect, legacy constructor deprecation.

SqliteItemRepository::syncFts() now consults the FieldRepository
for the per-category set of `searchable: true` field names and
filters the `items_fts.body` write accordingly. FullTextSearch::
rebuild() does the same in a single pre-pass over the fields table
plus per-item iteration.

Migration 0005_searchable_defaults.sql preserves existing FTS
coverage on upgrade by promoting all `text/longtext/editor/slug`
field rows to searchable=1 (matches the 2.2.0 factory defaults).
Verified against a copy of the live Scriptor schema: all 8
text-typed fields promote; password + fileupload stay at 0.

Backward compatibility: SqliteItemRepository's third constructor
arg (?FieldRepository) is optional. The 2.0/2.1 two-arg signature
keeps working — falls back to "index everything" with a one-time
E_USER_DEPRECATED notice on first FTS write.

Body composition extracted to FtsBody::compose() so the per-save
writer and the bulk rebuilder cannot drift on the format. The
plan called for per-process category-fields caching with event-
based invalidation; revisited and dropped: per-save fetch from
local SQLite is sub-millisecond, and the no-cache path can't go
stale in long-running CLI processes.

New test file SearchableFlagTest covers: opt-out per save,
structural name+label always indexed, update refreshes set,
rebuild respects flag, per-category isolation, flip-then-rebuild
contract, migration 0005 row-level effect, legacy constructor
deprecation.
@bigin bigin merged commit 855c4e7 into main May 17, 2026
4 checks passed
@bigin bigin deleted the feat/searchable-honored branch May 17, 2026 09:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant