Expand description
Search indexing and query utilities for the MoosicBox music catalog.
This crate provides Tantivy-backed indexing, mutation, and query functions used by the search API and database integration layers.
§MoosicBox Search
A full-text search implementation for the MoosicBox music ecosystem. Built on Tantivy, this package provides indexed search across artists, albums, and tracks in your music library.
§Features
- Full-Text Search: Fast text search across artists, albums, tracks, and metadata
- Tantivy Integration: Built on Rust’s high-performance search library
- Real-Time Indexing: Add, update, and delete documents from the index
- Fuzzy Matching: Find results even with typos or partial matches
- Ranking & Scoring: Relevance-based result ordering with custom boost logic
- Multi-Field Search: Search across artist, album, and track fields simultaneously
- Async Operations: Non-blocking index population and reindexing with Tokio
- API Integration: RESTful API endpoints for web applications (with
apifeature) - Index Management: Efficient index building, updating, and optimization
§Installation
Add this to your Cargo.toml:
[dependencies]
moosicbox_search = "0.1.4"§Usage
§Basic Search
use moosicbox_search::{global_search, search_global_search_index};
// High-level search (returns structured results)
let results = global_search("Pink Floyd", Some(0), Some(10))?;
// Process results
for result in results.results {
println!("Found: {:?}", result);
}
// Lower-level search (returns raw Tantivy documents)
let documents = search_global_search_index("Pink Floyd", 0, 10)?;§Populating the Index
use moosicbox_search::{populate_global_search_index, DataValue};
// Create data entries for indexing
let data = vec![
vec![
("document_type", DataValue::String("tracks".into())),
("artist_title", DataValue::String("Queen".into())),
("artist_id", DataValue::String("123".into())),
("album_title", DataValue::String("A Night at the Opera".into())),
("album_id", DataValue::String("456".into())),
("track_title", DataValue::String("Bohemian Rhapsody".into())),
("track_id", DataValue::String("789".into())),
("cover", DataValue::String("cover.jpg".into())),
("blur", DataValue::Bool(false)),
],
];
// Populate index (delete=true clears existing data first)
populate_global_search_index(&data, true).await?;§Deleting from Index
use moosicbox_search::{delete_from_global_search_index, DataValue};
// Delete by track ID
let delete_terms = vec![
("track_id_string", DataValue::String("789".into()))
];
delete_from_global_search_index(&delete_terms)?;§Reindexing
use moosicbox_search::reindex_global_search_index;
// Rebuild the entire index with fresh data
let fresh_data = vec![/* ... */];
reindex_global_search_index(&fresh_data).await?;§Working with Database Models (requires db feature)
use moosicbox_search::data::{AsDataValues, AsDeleteTerm, recreate_global_search_index};
use moosicbox_music_models::{Artist, Album, Track};
// Convert database models to search data
let artist = Artist { /* ... */ };
let data_values = artist.as_data_values();
// Get delete term for a model
let delete_term = artist.as_delete_term();
// Recreate index from scratch
recreate_global_search_index().await?;§Programming Interface
§Core Functions
// Search the global index
pub fn search_global_search_index(
search: &str,
offset: u32,
limit: u32,
) -> Result<Vec<NamedFieldDocument>, SearchIndexError>
// High-level search with structured results
pub fn global_search(
query: &str,
offset: Option<u32>,
limit: Option<u32>,
) -> Result<ApiSearchResultsResponse, SearchIndexError>
// Populate the index with data
pub async fn populate_global_search_index(
data: &[Vec<(&str, DataValue)>],
delete: bool,
) -> Result<(), PopulateIndexError>
// Delete documents from the index
pub fn delete_from_global_search_index(
data: &[(&str, DataValue)],
) -> Result<(), DeleteFromIndexError>
// Rebuild the entire index
pub async fn reindex_global_search_index(
data: &[Vec<(&str, DataValue)>],
) -> Result<(), ReindexError>§Data Types
#[derive(Debug, Clone)]
pub enum DataValue {
String(String),
Bool(bool),
Number(u64),
}§Error Types
pub enum SearchIndexError { /* ... */ }
pub enum PopulateIndexError { /* ... */ }
pub enum DeleteFromIndexError { /* ... */ }
pub enum ReindexError { /* ... */ }§Index Schema
The global search index includes the following fields:
document_type- Type of document: “artists”, “albums”, or “tracks”artist_title,artist_id- Artist informationalbum_title,album_id- Album informationtrack_title,track_id- Track informationcover- Cover art pathblur- Whether cover art should be blurreddate_released,date_added- Date fieldsversion_formats,version_bit_depths,version_sample_rates,version_channels,version_sources- Audio format metadata
Many string fields have variants for different search types (e.g., artist_title_search for tokenized search, artist_title_string for exact matching).
§Web API Endpoints
When the api feature is enabled:
GET /global-search?query={query}&offset={offset}&limit={limit}
GET /raw-global-search?query={query}&offset={offset}&limit={limit}To register these routes on an Actix scope:
use actix_web::web;
use moosicbox_search::api::bind_services;
let scope = bind_services(web::scope(""));§API Usage Examples
# Structured search results
curl "http://localhost:8000/global-search?query=pink%20floyd&limit=10"
# Raw Tantivy document results
curl "http://localhost:8000/raw-global-search?query=rock&offset=0&limit=20"§Search Algorithm
The search implementation uses multiple query strategies with different boost factors:
- Exact match: Highest boost for exact phrase matches
- Prefix match: Medium boost for prefix matching with fuzzy search
- Fuzzy match: Base boost for fuzzy matching with typo tolerance
Search queries are sanitized to remove special characters and searches are performed across multiple field combinations optimized for artists, albums, and tracks.
§Features
default: Enablesapi,db, andopenapifeaturesapi: Enables Actix-web REST API endpointsdb: Enables database integration and model conversion traitsopenapi: Enables OpenAPI documentation supportsimulator: Enables filesystem simulation for testing
§Testing
# Run all tests
cargo test
# Run with specific features
cargo test --features "api,db"§Error Handling
use moosicbox_search::{global_search, SearchIndexError};
match global_search("query", Some(0), Some(10)) {
Ok(results) => {
println!("Found {} results", results.results.len());
}
Err(SearchIndexError::GetGlobalSearchIndex(e)) => {
eprintln!("Index error: {}", e);
}
Err(SearchIndexError::QueryParser(e)) => {
eprintln!("Invalid query: {}", e);
}
Err(e) => eprintln!("Search error: {}", e),
}§Implementation Notes
- The search index is stored at
{config_dir}/search_indices/global_search_indexby default - In test mode, uses an in-memory index
- Index writer uses a 50MB memory budget by default
- Search operations use query sanitization to handle special characters
- The implementation includes custom boost logic to prioritize exact matches and specific document types
§See Also
moosicbox_music_api_models- Search API modelsmoosicbox_music_models- Music data modelsmoosicbox_library- Music library managementmoosicbox_scan- Library scanning and indexing
Modules§
Enums§
- Create
Index Error - Error type for failures when creating a search index.
- Data
Value - Represents a data value that can be indexed in the search system.
- Delete
From Index Error - Error type for failures when deleting from a search index.
- GetGlobal
Search Index Error - Error type for failures when retrieving the global search index.
- GetGlobal
Search Reader Error - Error type for failures when retrieving the global search index reader.
- GetIndex
Reader Error - Error type for failures when retrieving an index reader.
- Populate
Index Error - Error type for failures when populating a search index.
- Recreate
Index Error - Error type for failures when recreating a search index.
- Reindex
Error - Error type for failures when reindexing a search index.
- Search
Index Error - Error type for failures when searching a search index.
Functions§
- delete_
from_ global_ search_ index - Deletes documents from the global search index by matching field values.
- global_
search - Performs a global search and returns structured API results.
- populate_
global_ search_ index - Populates the global search index with the provided data.
- populate_
global_ search_ index_ sync - Populates the global search index with the provided data synchronously.
- reindex_
global_ search_ index - Reindexes the global search index by recreating it from scratch with new data.
- search_
global_ search_ index - Searches the global search index and returns raw Tantivy documents.