adminx-search
Full-text search for adminx, powered by the standalone
searchezcrate.
A resource declares its searchable fields; adminx then keeps the index in sync automatically — create/update index the record, delete removes it — and the list page grows a search box. Leave it out and adminx behaves exactly as before, with no extra queries.
How it fits together
adminx-core the Indexer seam + the ?q= search box on the list page
adminx-search ←── drives a searchez::Backend behind that seam (this crate)
searchez the standalone search-model layer (in-memory / Meilisearch)
searchez is a general-purpose crate that knows nothing about adminx. This crate
is just the glue: it maps adminx's neutral Indexer seam onto a searchez::Backend.
Swap the backend without touching your resources.
Install
[]
= { = "3", = ["axum", "seaorm", "search"] }
For the Meilisearch backend, use search-meilisearch instead of search.
Use
// 1. storage first
set_storage;
// 2. register a search backend — in-memory (BM25), no external service
init_memory;
// 3. the rest of your app
configure_auth;
register_resource;
A resource opts in by listing its searchable columns:
That's it. The Posts list page now shows a search box; ?q=rust returns matches
ranked by relevance, and every create/update/delete keeps the index current.
Backfilling
The in-memory backend is non-persistent, so seed it from the database at startup (and after any restart):
let page = storage.list.await?;
reindex.await?;
A persistent backend (Meilisearch) keeps its index across restarts, so this is only needed once — or after switching backends.
Backends
In-memory (feature search)
init_memory() uses searchez's BM25 in-memory engine. No external service —
ideal for development and small single-process datasets. Non-persistent (see
Backfilling).
Meilisearch (feature search-meilisearch)
A production backend backed by a Meilisearch server:
let backend = new?;
init;
Nothing about your resources changes. (searchez's Meilisearch backend is compile-verified but not yet exercised against a live server in CI — see the searchez README.)
What is and isn't indexed
- ✅ Every resource using the default CRUD that declares
search_fields()— API and HTML forms alike, because the hook lives on the sharedcrudfunctions (the same seamadminx-audituses). - ✅ Only the declared fields go into the search document; other columns are not indexed. The record is read back after each write, so a partial update still indexes the full field set.
- ⚠️ Indexing is best-effort: a search-backend failure is logged, never
propagated — it can't fail the write the user asked for. The index catches up
on the next write or a
reindex. - ❌ Writes that bypass adminx entirely (a migration,
psql, another service) don't update the index; runreindexto reconcile.
License
MIT