This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
rsearch is a production-grade query translation service that converts OpenSearch/Elasticsearch-style query strings into database-specific formats (PostgreSQL SQL with parameterized queries). It acts as a lightweight bridge between application search UIs and databases.
Core flow: Query string -> Parser -> AST -> Translator -> WHERE clause + parameters
# Build
go build -o bin/rsearch cmd/rsearch/main.go
make build
# Run all tests
go test ./...
make test
# Run specific package tests
go test ./internal/parser/...
go test ./internal/translator/...
go test ./internal/schema/...
# Run a single test
go test -run TestParsePhraseQuery ./internal/parser/...
# Regenerate syntax documentation from test cases
go run cmd/gendocs/main.go
# Start demo environment (Docker + rsearch + opens browser)
make demo
# Start/stop services
make start
make stopcmd/
rsearch/ Entry point, server setup
gendocs/ Documentation generator from test cases
internal/
parser/ Lexer, recursive descent parser, AST nodes
translator/ Translator interface, PostgreSQL implementation
schema/ Schema registry with RWMutex, field resolution
api/ HTTP handlers (chi router), middleware
config/ Configuration loading (viper)
observability/ Structured logging (zerolog), Prometheus metrics
pkg/rsearch/ Public types
tests/
testcases.json Test cases used for docs generation
schemas.json Test schemas
examples/
demo.html Interactive web demo UI
- Parser (
internal/parser/): Tokenizes query string via Lexer, builds AST using recursive descent - Schema (
internal/schema/): Resolves field names (camelCase -> snake_case), validates against registered schema - Translator (
internal/translator/): Converts AST to SQL with parameterized queries ($1, $2...)
AST Nodes (internal/parser/ast.go):
BinaryOp,UnaryOp- boolean operators (AND, OR, NOT)FieldQuery,FieldGroupQuery- field:value and field:(a OR b)RangeQuery- [start TO end], {start TO end}, >=, <GroupQuery- parenthesized expressions (a OR b)RequiredQuery,ProhibitedQuery- +term, -termTermQuery,PhraseQuery,WildcardQuery- standalone queriesFuzzyQuery,ProximityQuery,BoostQuery,ExistsQuery- Value nodes:
TermValue,PhraseValue,WildcardValue,RegexValue,NumberValue
Translator (internal/translator/postgres.go):
Supported node translations:
FieldQuery- handles term, phrase, wildcard, regex valuesBinaryOp- AND/OR with proper parenthesesUnaryOp- NOT operatorRangeQuery- BETWEEN, comparison operators, unbounded rangesGroupQuery- parenthesized SQLRequiredQuery- pass-throughProhibitedQuery- NOT prefixExistsQuery- IS NOT NULLBoostQuery- SQL unchanged, boost stored in metadataFuzzyQuery- levenshtein() (requires pg_trgm)ProximityQuery- phraseto_tsquery() (requires FTS)FieldGroupQuery- field:(a OR b) expansion
Schema (internal/schema/schema.go):
- Field types: text, integer, float, boolean, datetime, date, time, json, array
- Options: namingConvention, strictOperators, strictFieldNames, defaultField
- EnabledFeatures: fuzzy (pg_trgm), proximity (FTS), regex
OR -> AND -> NOT -> Required/Prohibited (+/-) -> Field (:) -> Boost (^) -> Fuzzy (~)
Field queries:
field:value- exact matchfield:"phrase"- phrase matchfield:wild*- wildcard (LIKE)field:/regex/- regex match (~)
Boolean operators:
AND,&&- conjunctionOR,||- disjunctionNOT,!- negation+term- required (pass-through)-term- prohibited (NOT)- Implicit OR:
term1 term2->term1 OR term2
Ranges:
[50 TO 500]- inclusive (BETWEEN){50 TO 500}- exclusive (> AND <)[50 TO 500}- mixed>=50,>50,<=100,<100- comparison[100 TO *]- unbounded
Advanced:
field:term~2- fuzzy search (levenshtein)"phrase"~5- proximity search (FTS)field:value^2- boost (metadata only for SQL)_exists_:field- existence check (IS NOT NULL)
Grouping:
(a OR b) AND c- parenthesesfield:(a OR b)- field group
POST /api/v1/translate- Translate query stringPOST /api/v1/schemas- Register schemaGET /api/v1/schemas/{name}- Get schemaDELETE /api/v1/schemas/{name}- Delete schemaGET /health- Health checkGET /ready- Readiness checkGET /metrics- Prometheus metrics (when enabled)
Environment variables prefixed with RSEARCH_:
RSEARCH_SERVER_PORT=8080
RSEARCH_LOGGING_LEVEL=debug
RSEARCH_LOGGING_FORMAT=console # or json
RSEARCH_METRICS_ENABLED=true- Operators are normalized to keyword form (&&->AND, ||->OR, !->NOT) during parsing
- All SQL uses parameterized queries for security ($1, $2...)
- Schema field names support case-insensitive matching and aliasing
- Naming conventions transform field names (productCode -> product_code)
- Standalone terms/wildcards require
defaultFieldin schema options - Fuzzy search requires
enabledFeatures.fuzzy: trueand pg_trgm extension - Proximity search requires
enabledFeatures.proximity: trueand FTS setup - Documentation auto-generated from
tests/testcases.jsonviacmd/gendocs