Skip to content
GitHubDiscord

Search (lexigram-search)

Full-text search and indexing for Lexigram Framework — Elasticsearch, Meilisearch, and Algolia


lexigram-search provides a unified SearchEngineProtocol interface over Meilisearch, Elasticsearch, Typesense, PostgreSQL full-text, MySQL, MongoDB, and SQLite. It supports typo-tolerant search, faceting, fuzzy matching, result caching, and analytics. All services are wired via SearchProvider, which registers the search engine protocol with the DI container.


Terminal window
uv add lexigram-search
# Optional extras
uv add "lexigram-search[meilisearch]" # Meilisearch
uv add "lexigram-search[elasticsearch]" # Elasticsearch 8.x
uv add "lexigram-search[typesense]" # Typesense
uv add "lexigram-search[postgres,mysql,sqlite,mongodb]" # Database backends
from lexigram import Application
from lexigram.di.module import Module, module
# Import the module from the package
from lexigram.search import SearchModule
@module(imports=[SearchModule.configure(...)])
class AppModule(Module):
pass
app = Application(modules=[AppModule])
if __name__ == "__main__":
app.run()

Zero-config usage: Call SearchModule.configure() with no arguments to use defaults.

application.yaml
search:
backend_type: meilisearch
meilisearch:
url: http://localhost:7700
api_key: "${MEILI_API_KEY}"
query:
strategy: fuzzy
default_limit: 10
Section titled “Option 2 — Profiles + Environment Variables (recommended)”
Terminal window
export LEX_SEARCH__ENABLED=true
# Environment variables for each field
from lexigram.search.config import SearchConfig, BackendType
from lexigram.search import SearchModule
config = SearchConfig(backend_type=BackendType.MEILISEARCH, ...)
SearchModule.configure(config)
FieldDefaultEnv varDescription
backend_typememoryLEX_SEARCH__BACKEND_TYPEActive backend (meilisearch, elasticsearch, typesense, postgres, mysql, sqlite, memory)
timeout30.0LEX_SEARCH__TIMEOUTDefault request timeout in seconds
query.strategyfuzzyLEX_SEARCH__QUERY__STRATEGYQuery strategy (fuzzy, exact, semantic, hybrid)
query.default_limit10LEX_SEARCH__QUERY__DEFAULT_LIMITDefault number of results returned
query.max_limit100LEX_SEARCH__QUERY__MAX_LIMITMaximum allowed result limit
query.fuzzy_threshold0.8LEX_SEARCH__QUERY__FUZZY_THRESHOLDFuzzy match threshold (0–1; 1 = exact)
meilisearch.urlhttp://localhost:7700LEX_SEARCH__MEILISEARCH__URLMeiliSearch server URL
meilisearch.api_keynullLEX_SEARCH__MEILISEARCH__API_KEYMeiliSearch authentication key
elasticsearch.hosts[http://localhost:9200]LEX_SEARCH__ELASTICSEARCH__HOSTSElasticsearch cluster hosts
operations.bulk_chunk_size500LEX_SEARCH__OPERATIONS__BULK_CHUNK_SIZEDocuments per bulk index request
MethodDescription
SearchModule.configure(config, enable_facets)Configure with explicit SearchConfig
SearchModule.stub()Minimal config for testing
  • Protocol abstraction — Swap backends without changing application code
  • Meilisearch — Typo-tolerant, instant search with faceting
  • Elasticsearch — Full Lucene query DSL; aggregations; multi-index
  • Typesense — Fast, schema-enforced search with scoped API keys
  • PostgreSQL FTStsvector/tsquery via lexigram-sql; no extra infra
  • MySQL FTSFULLTEXT index support for MySQL / MariaDB
  • MongoDB Text — Native $text operator with language stemming
  • SQLite FTS5 — Local development with zero dependencies
  • Cached search — Transparent result caching via CacheBackend
  • Analytics — Query recording and hit-rate analytics for ranking improvement
async with Application.boot(modules=[SearchModule.stub()]) as app:
# your test code
...
FileWhat it contains
src/lexigram/search/module.pySearchModule class with factory methods
src/lexigram/search/di/provider.pySearchProvider — wires search protocols into DI container
src/lexigram/search/config.pySearchConfig and sub-config classes
src/lexigram/search/engine/Search engine implementations for each backend
src/lexigram/search/indexer/Index management and document indexing