sync_engine/search/mod.rs
1//! Search Infrastructure
2//!
3//! Full-text search across items using RediSearch and MySQL.
4//!
5//! # Architecture
6//!
7//! ```text
8//! QueryBuilder (AST)
9//! ↓
10//! ├─→ RediSearchTranslator → FT.SEARCH syntax
11//! └─→ SqlTranslator → MySQL JSON_EXTRACT queries
12//! ```
13//!
14//! # Index Registration
15//!
16//! sync-engine stays "dumb" about content but provides index lifecycle management:
17//!
18//! ```rust,no_run
19//! # use sync_engine::{SyncEngine, search::{SearchIndex, Query}};
20//! # async fn example(engine: &SyncEngine) {
21//! // Register schema at startup using builder pattern
22//! let index = SearchIndex::new("users", "crdt:users:")
23//! .text_sortable("name")
24//! .text("email")
25//! .numeric_sortable("age")
26//! .tag("roles");
27//!
28//! engine.create_search_index(index).await.unwrap();
29//!
30//! // RediSearch auto-indexes matching JSON documents
31//! // Search using Query AST
32//! let query = Query::field_eq("name", "Alice");
33//! let results = engine.search("users", &query).await.unwrap();
34//! # }
35//! ```
36//!
37//! # Query Language (Lucene/RediSearch syntax)
38//!
39//! ```text
40//! @name:Alice - Field equals
41//! @age:[25 40] - Numeric range
42//! @tags:{rust|database} - Tag membership (OR)
43//! @name:Alice AND @age:[25 40] - Boolean AND
44//! @status:active | @status:pending - Boolean OR
45//! -@deleted:true - Boolean NOT
46//! @name:*alice* - Wildcard contains
47//! @name:ali* - Prefix match
48//! @name:%alice% - Fuzzy match (Levenshtein)
49//! ```
50
51mod query_builder;
52mod redis_translator;
53mod sql_translator;
54mod index_manager;
55mod search_cache;
56
57pub use query_builder::{Query, QueryBuilder, QueryNode, FieldQuery, FieldOperator, QueryValue};
58pub use redis_translator::RediSearchTranslator;
59pub use sql_translator::{SqlTranslator, SqlQuery, SqlParam};
60pub use index_manager::{IndexManager, SearchIndex, SearchField, SearchFieldType};
61pub use search_cache::{SearchCache, SearchCacheStats};