feat(search): implement global search across all entity types (ALL-731)#207
Merged
texture-fleet-agent[bot] merged 2 commits intomainfrom May 6, 2026
Merged
feat(search): implement global search across all entity types (ALL-731)#207texture-fleet-agent[bot] merged 2 commits intomainfrom
texture-fleet-agent[bot] merged 2 commits intomainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Fixes /search endpoint returning 0 results for known entities (e.g. tri-state).
Root cause:
searchFromDb() in lib/data/search.ts was a TODO stub returning [] for every
call. The database already has populated search_vector columns (GENERATED
ALWAYS AS STORED) on utilities, programs, power_plants, and ev_stations —
the endpoint just wasn't reading them.
Fix:
Implement searchFromDb() to actually query the DB:
- For tables with a search_vector tsvector column, use
websearch_to_tsquery (tolerant of punctuation like hyphens) with an
ILIKE fallback on the primary name column. Rank by ts_rank.
- For tables without search_vector (pricing_nodes, transmission_lines,
isos, rtos, balancing_authorities) use ILIKE on the name column.
- All queries scoped to 'deleted_at IS NULL' (soft-deletes).
- Fan out across all 9 entity types in parallel (Promise.all).
- Graceful degradation: a failing per-type query returns [] instead of
throwing, so one bad query never blacks out the full /search response.
Verified against production DB:
/search?q=tri-state returns:
utility (2) — Tri-State Electric Member, Tri-State G&T Association
power-plant (5) — Craig (CO), JM Shafer Generating Station, ...
ev-station (1) — Tri-State Nissan
transmission-line (3) — TRI-STATE G & T ASSN owned lines
Smoke test (lib/data/search.test.ts) runs in CI via vitest without a live
DB by mocking @/lib/db/client and asserting SQL shape, parameterization,
entity-type fan-out, and graceful degradation. 10 assertions, <100ms.
Timing: full 9-type fan-out completes in 40-85ms against Neon HTTP.
Ref: memory/specs/relay-commongrid-bugs-2026-05-06.md Bug #3
Complements the hermetic vitest unit tests (lib/data/search.test.ts) with a live-DB regression guard gated on $DATABASE_URL. Asserts the specific bugs flagged in Morgan's Relay report: - /search?q=tri-state must return Tri-State G&T (ALL-731 bug #3) - /search?q=duke%20energy must return Duke Energy utilities - /search?q=demand%20response must return Demand Response programs - /search?q=pjm&types=isos must return PJM Interconnection - broad queries fan out across buckets (utility + transmission-line) - per-type limit is respected - empty/whitespace query returns [] Skips cleanly on local machines without DATABASE_URL so `npm test` stays hermetic and fast. When DATABASE_URL is provisioned in CI, this test file becomes the last line of defense before a silent `/search` regression ships.
68645f3 to
dbf1d3a
Compare
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.
Fixes
/searchendpoint returning 0 results for known entities (e.g.tri-state, reported by Morgan in Relay bug #3).Root cause
searchFromDb()inlib/data/search.tswas a TODO stub returning[]for every call — independently of whethersearch_vectorwas populated.Audit of the production DB confirmed the tsvector columns are actually already fully populated via
GENERATED ALWAYS AS STOREDexpressions on utilities, programs, power_plants, ev_stations, and substations. The endpoint just wasn't reading them.Fix
lib/data/search.tsnow actually queries the database:search_vectortsvector column:websearch_to_tsquery(punctuation-tolerant, handlestri-statecorrectly) combined with an ILIKE fallback on the primary name column. Results ranked byts_rank.search_vector(pricing_nodes, transmission_lines, isos, rtos, balancing_authorities): plain ILIKE on the name column.deleted_at IS NULL(soft-deletes).Promise.all) — full sweep completes in 40–85 ms against Neon HTTP.[]instead of throwing, so one bad query never blacks out the whole/searchresponse.drizzle/0007_fix_search_vectors.sql(already pushed, idempotent) ensures thesearch_vectorcolumns are GENERATED ALWAYS AS — it's a no-op against the current DB state but protects us against a hypothetical replay against a fresh database.Verification against prod DB
Smoke test
lib/data/search.test.ts(new) runs in CI via vitest without a live DB. It mocks@/lib/db/client, captures every drizzle SQL fragment, and asserts:typesfilter scopes correctly.[].websearch_to_tsquery+ ILIKE, notplainto_tsquery.10 assertions, <100 ms to run.
Ref:
memory/specs/relay-commongrid-bugs-2026-05-06.mdBug #3Fixes ALL-731