feat(search): match Elasticsearch token semantics exactly (PPT-2644) - #446
Merged
Conversation
Multi-word queries are now OR-joined whole-word matches with a prefix on the final token only — precisely what the old simple_query_string plus Neuroplastic's trailing * produced — replacing the AND-of-prefixes the initial migration shipped. Email-shaped input stays a single quoted whole-address lexeme so user lookup keeps the precision the old field-scoped phrase match provided (OR-splitting an address would match everyone on its domain). Adds the previously-missing dedicated sanitizer spec (9 cases incl. the never-500 vectors). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greptile SummaryThis PR restores Elasticsearch-compatible token semantics for PostgreSQL text search while replacing placeholder-based email handling with collision-free tokenization.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| src/placeos-rest-api/utilities/text-search.cr | Restores OR-based Elasticsearch token behavior and replaces collision-prone email placeholders with ordered single-pass tokenization. |
| spec/text_search_spec.cr | Adds focused coverage for token joining, final-token prefixes, syntax degradation, emails, collision handling, Unicode, and resource caps. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Free-form query] --> B[Cap input length]
B --> C[Single-pass tokenizer]
C --> D{Token type}
D -->|Email| E[Quoted whole-address lexeme]
D -->|Field prefix| F[Discard]
D -->|Operator| G[Discard]
D -->|Plain word| H[Word lexeme]
E --> I[Cap token count]
H --> I
I --> J[OR-join tokens]
J --> K[Prefix final token only]
Reviews (2): Last reviewed commit: "refactor(search): tokenize in a single o..." | Re-trigger Greptile
Replaces the email placeholder substitution with one scan that captures addresses, consumes field: prefixes and collects words in position order. Eliminates the placeholder-collision edge Greptile flagged (a literal 'placeosemailtokenNx' alongside an email hijacked the mapping) and the latent email-followed-by-colon interaction — both now spec-pinned. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Part of PPT-2644. Follow-up to #445, restoring exact Elasticsearch token semantics for multi-word
qto avoid behavioral regressions against the pre-migration platform.What changes
simple_query_stringdid: a record matches when any term matches.*to the query's final token; earlier terms were whole-word matches. Now identical. (sydney roo= whole-wordsydneyOR prefixroo— the term being typed still autocompletes.)q=<address>would OR-split and match every user on the domain. Old clients had precise email lookup via the (now accepted-and-ignored)fields=emailphrase path, so email-shaped input is kept as a single whole-address lexeme — the vectors index addresses both whole and tokenized for exactly this.Utils::TextSearchspec (nine cases: the never-500 vectors, ES-syntax degradation, email handling, token/length caps, unicode).Notes for reviewers
X-Total-Countgrows accordingly. This is the intended ES parity.