Skip to content

feat: replace Elasticsearch with PostgreSQL full-text search (PPT-2644, 2/2) - #443

Closed
camreeves wants to merge 3 commits into
masterfrom
PPT-2644-pg-full-text-search
Closed

feat: replace Elasticsearch with PostgreSQL full-text search (PPT-2644, 2/2)#443
camreeves wants to merge 3 commits into
masterfrom
PPT-2644-pg-full-text-search

Conversation

@camreeves

@camreeves camreeves commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Opened prematurely — closed pending internal review. Work continues on the branch (PPT-2644).

camreeves and others added 3 commits August 6, 2026 02:58
…on (PPT-2644)

- Utils::TextSearch: never-500 q -> tsquery sanitizer (AND of prefix tokens)
- application.cr: search_tsquery/search_limit/search_offset + paginate_search;
  fix the Link header off-by-one that skipped one row per page
- modules: parent-driver search via EXISTS join (has_parent parity); scoped
  listing now uses IN() (the ES version returned nothing for >1 visible module)
- zones: tree/tag filters in SQL, children counts via GROUP BY
- drivers: straight conversion

NOTE: pg-orm 2.2.x Collections cannot compile a single-argument raw where()
(NamedTuple-in-union overload) — always pass bind args.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…PT-2644)

- docker-compose: remove elastic + search-ingest services/anchors
- spec/helper: remove refresh_elastic/ensure_keyword_mapping/clear_elastic
- test_base_index macro: synchronous save->query->assert (no index lag)
- root.cr: /reindex + /backfill deprecated no-ops; search_ingest out of the
  cluster version fan-out; require removed
- shard.yml/lock: search-ingest dependency removed (neuroplastic remains
  transitively via placeos-models until the models major drops it)
- spec/migration: TEMPORARY models branch pin (revert before merge)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…2644)

All 24 Elasticsearch-backed controllers now query PostgreSQL directly:
filters become SQL WHERE clauses, q matches the generated search_vector
columns, and ES parent-child becomes EXISTS joins (modules<->driver,
system-triggers<->trigger, systems<->trigger instances,
assets<->asset_type). paginate_results and the ES spec helpers are gone.

Deliberate behavior fixes (each spec-pinned):
- systems?trigger_id= worked never (unsatisfiable ES query) — real join
- systems?email= was a no-op alone and WIDENED the group/subsystem zone
  scope when combined — now a strict AND filter
- scoped (non-admin) module listing returned [] when the user could
  access more than one module — now IN()
- alerts multi-dashboard scoping matched nothing for authorities with
  more than one dashboard — now IN()
- alerts?enabled=false and asset_categories?hidden=false were ignored
  (falsy-Bool) — now filter both values
- system-triggers q was silently ignored — now matches the parent
  trigger's text
- assets can now be searched by asset-type name (previously a TODO)

Known ES-era quirks preserved: zones/assets/pending_mails multi-zone
AND-containment, public/important/triggered only-when-true filters,
undecrypted settings search results.

pg-orm gotchas encoded: never single-arg raw where (does not compile);
arrays cannot bind as one parameter — sql_array() splices per-element
placeholders; empty arrays guard with an empty-page short-circuit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the type: enhancement new feature or request label Aug 5, 2026
@camreeves camreeves closed this Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: enhancement new feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant