feat: Lucene query parser with sql and dynamodb support#124
feat: Lucene query parser with sql and dynamodb support#124Lutherwaves wants to merge 11 commits intomainfrom
Conversation
|
Moving to draft to refactor a bit for better readability and consistency |
…itions Added 34 search query examples to types/types.go covering all Lucene search capabilities: - Basic field search (exact match, wildcards) - Boolean operators (AND, OR, NOT) - Required/Prohibited operators (+, -) - Range queries (inclusive, exclusive, open-ended, date ranges) - Quoted phrases and special characters - Complex nested queries - Implicit search across all string fields - JSONB/nested field access with dot notation - Null value queries - Fuzzy search with edit distance These examples can be referenced in Swagger annotations using: $ref: "#/components/examples/SearchQueryBasic" $ref: "#/components/examples/SearchQueryWildcard" etc. This allows API consumers to easily understand and use the Lucene query syntax for filtering and searching resources, similar to how PatchBody provides examples for PATCH operations. Related to PR tink3rlabs#124 which added Lucene search support.
…efinitions
Added SearchQuery schema to types/types.go with 34 comprehensive examples
covering all Lucene search capabilities:
Schema Structure:
- Type: string
- Description: Full Lucene query syntax reference
- Default example: "name:john AND status:active"
- 34 example queries covering:
* Basic field searches and wildcards
* Boolean operators (AND, OR, NOT, +, -)
* Range queries (inclusive, exclusive, open-ended, dates)
* Quoted phrases and escaped characters
* Complex nested queries
* Implicit search across string fields
* JSONB/nested field access (field.subfield:value)
* Null value queries (field:null)
* Fuzzy search (term~, term~2)
Usage in Swagger/OpenAPI annotations:
schema:
$ref: "#/components/schemas/SearchQuery"
Or in Go swaggo annotations:
// @param query query string false "Search query" SchemaExample(SearchQuery)
This provides a reusable schema definition similar to PatchBody, making it
easy for API consumers to understand and use Lucene query syntax for filtering
and searching resources.
Related to PR tink3rlabs#124 which added Lucene search support.
…efinitions
Added SearchQuery schema to types/types.go with 34 comprehensive examples
covering all Lucene search capabilities:
Schema Structure:
- Type: string
- Description: Full Lucene query syntax reference
- Default example: "name:john AND status:active"
- 34 example queries covering:
* Basic field searches and wildcards
* Boolean operators (AND, OR, NOT, +, -)
* Range queries (inclusive, exclusive, open-ended, dates)
* Quoted phrases and escaped characters
* Complex nested queries
* Implicit search across string fields
* JSONB/nested field access (field.subfield:value)
* Null value queries (field:null)
* Fuzzy search (term~, term~2)
Usage in Swagger/OpenAPI annotations:
schema:
$ref: "#/components/schemas/SearchQuery"
Or in Go swaggo annotations:
// @param query query string false "Search query" SchemaExample(SearchQuery)
This provides a reusable schema definition similar to PatchBody, making it
easy for API consumers to understand and use Lucene query syntax for filtering
and searching resources.
Related to PR tink3rlabs#124 which added Lucene search support.
|
@deanefrati @ayashjorden if anyone has some time to review, I also tested on a service using PSQL - all works as expected, see description for full examples. |
ayashjorden
left a comment
There was a problem hiding this comment.
LGTM, Please add unit-tests
|
One additional thing I will be adding is the ability to instatiate the parser with some fields which are excluded from implicit search for multi-tenancy |
@ayashjorden Ready |
| }, | ||
| }, | ||
| { | ||
| name: "duplicate field names (last wins)", |
There was a problem hiding this comment.
Havan't read upstream docs, just make sure that we document this, both in func comments and in Magic README.md (or the appropriate sub-readme
There was a problem hiding this comment.
Good catch, I think it would be better to error out if there are conflicting types, making hte query invalid.
ayashjorden
left a comment
There was a problem hiding this comment.
@Lutherwaves, This is a mammoth of a PR, I've added static-is comments suggesting simplifications or brevity.
Not sure how to go about approving it, @deanefrati as a production user, if you have an idea?
Updates were made, tests were added, I'm ok with the PR, but Dean needs to also take a look as he's using it in several places.
|
@ayashjorden thanks for the review, I will look into the suggestions. WRT the size - splitting this PR just to make it smaller, while I agree with the intention behind it, seems overkill in this case. This is a new, backwards compatible extension of the previous feature and the majority of lines come from the unit tests. |
|
I didn't hint to split it, just stated that it's a mammoth to review
…On Sun, Jan 18, 2026, 10:23 PM Martin Yankov ***@***.***> wrote:
*Lutherwaves* left a comment (tink3rlabs/magic#124)
<#124 (comment)>
@ayashjorden <https://github.com/ayashjorden> thanks for the review, I
will look into the suggestions. WRT the size - splitting this PR just to
make it smaller, while I agree with the intention behind it, seems overkill
in this case. This is a new, backwards compatible extension of the previous
feature and the majority of lines come from the unit tests.
—
Reply to this email directly, view it on GitHub
<#124 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABACOU4G4YYQJIA7W4Y2IM34HRZ6NAVCNFSM6AAAAACQDYAUI2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTONRWGYYDENZWGQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
It's literally an eye strain to review, I really appreciate you taking the time. |
|
@ayashjorden to the best of my prompt & review skills, I addressed the review. |
dfcf68b to
66595d3
Compare
|
That's indeed a behemoth of a PR :) would you be able to add some usage instructions for developers for how to use this new functionality? I would like to test it in one of my services to make sure it works in real life... |
It is basically the StorageAdapter.Search method now accepts proper lucene. I have tested it extensively on postgresql and somewhat with sqlite, but not in dynamodb. Check the PR description for all examples. Happy to prompt up some docs before we merge if you think this would add value. |
Implements Apache Lucene query syntax parser using go-lucene library with custom drivers for PostgreSQL (JSONB) and DynamoDB PartiQL. Supports field:value queries, wildcards, ranges, boolean operators, quoted phrases, fuzzy search, implicit search expansion, and JSONB field notation. Includes field validation, security limits, and comprehensive test coverage.
- Remove driver storage redundancy - Simpler and more configurable parser initi - Make security limits and tag names configurable - Clean up unused code
- NewParser(model) replaces NewParserFromType(model) - Implicit search restricted to string fields only - Removed complex tag configuration - Split driver.go into postgres_driver.go and dynamodb_driver.go - NewPostgresDriver() and NewDynamoDBDriver() constructors - Checks for JSONB/JSON in type name, maps, and structs - Parse-time validation (HTTP 400) not runtime (HTTP 500)
…ySQL, and SQLite - Renamed postgres_driver.go to sql_driver.go for generic SQL support - Refactored PostgresJSONBDriver to SQLDriver with provider field - Added provider-specific switch statements for: * Case-insensitive LIKE (ILIKE vs LOWER() vs LIKE) * Fuzzy search (similarity() vs SOUNDEX() vs error) * JSON field extraction (JSONB ->> vs JSON_EXTRACT) * Parameter placeholders ($N vs ?) - Updated ParseToSQL() to accept provider string parameter - Updated SQLAdapter.Search() to pass provider to parser - Updated all tests to include "postgresql" provider parameter - PostgreSQL: ILIKE, ::text casting, similarity(), JSONB ->> operators, $N placeholders - MySQL: LOWER() + LIKE, JSON_UNQUOTE(JSON_EXTRACT()), SOUNDEX(), ? placeholders - SQLite: LIKE (case-insensitive), JSON_EXTRACT(), no fuzzy search, ? placeholders
…efinitions Schema Structure: - Type: string - Description: Full Lucene query syntax reference - Default example: "name:john AND status:active" - 34 example queries covering: * Basic field searches and wildcards * Boolean operators (AND, OR, NOT, +, -) * Range queries (inclusive, exclusive, open-ended, dates) * Quoted phrases and escaped characters * Complex nested queries * Implicit search across string fields * JSONB/nested field access (field.subfield:value) * Null value queries (field:null) * Fuzzy search (term~, term~2)
- Escape PartiQL values in DynamoDB driver - Add lucene query openapi - Simplify tests
…rs.Join, refactor to regex validation
…holder handling * Use JSON struct tags instead of Go field names for cursor value extraction * Remove PostgreSQL pre-conversion that conflicted with GORM's placeholders
Implements Apache Lucene query syntax parser by extending https://github.com/grindlemire/go-lucene with custom drivers for SQL (JSONB) and DynamoDB PartiQL.
Supports field:value queries, wildcards, ranges, boolean operators, quoted phrases, fuzzy search, implicit search support for text fields only, and JSONB columns support. Includes field validation, security limits, and added tests.
PostgreSQL
MySQL
SQLite
DynamoDB
Example Queries and SQL Translation
Basic Field Search
Query: name:john
Wildcard Search (Case-Insensitive)
Query: name:john*
Wildcard Contains
Query: name:john
Fuzzy Search
Query: name:roam~2
JSON Field Access
Query: labels.env:prod
JSON Field Wildcard
Query: labels.category:backend*
Boolean AND
Query: name:john AND status:active
Boolean OR
Query: status:active OR status:pending
Range Query (Inclusive)
Query: age:[18 TO 65]
Range Query (Open-Ended)
Query: age:[18 TO *]
Null Check
Query: parent_id:null
NOT Operator
Query: NOT status:deleted
Complex Query
Query: (name:john* OR email:*@example.com) AND status:active