use std::collections::{HashMap, HashSet};
use std::sync::{Arc, Mutex};
use nodedb_types::result::SearchResult;
use nodedb_types::text_search::TextSearchParams;
use crate::engine::crdt::CrdtEngine;
use crate::engine::fts::state::FtsState;
use crate::error::LiteError;
use crate::nodedb::convert::loro_value_to_document;
use crate::nodedb::lock_ext::LockExt;
pub(crate) struct TextSearchRequest<'a> {
pub collection: &'a str,
pub field: &'a str,
pub query: &'a str,
pub top_k: usize,
pub params: &'a TextSearchParams,
pub allowed_ids: Option<&'a HashSet<String>>,
}
pub(crate) fn run_text_search(
fts_state: &Arc<FtsState>,
crdt: &Arc<Mutex<CrdtEngine>>,
req: TextSearchRequest<'_>,
) -> Result<Vec<SearchResult>, LiteError> {
let raw = {
let mgr = fts_state.manager.lock_or_recover();
match req.allowed_ids {
Some(ids) => mgr.search_with_allowed(
req.collection,
req.field,
req.query,
req.top_k,
req.params,
ids,
)?,
None => mgr.search(req.collection, req.field, req.query, req.top_k, req.params)?,
}
};
let crdt_guard = crdt.lock_or_recover();
Ok(raw
.into_iter()
.map(|r| {
let metadata = match crdt_guard.read(req.collection, &r.doc_id) {
Some(loro_val) => loro_value_to_document(&r.doc_id, &loro_val).fields,
None => HashMap::new(),
};
SearchResult {
id: r.doc_id,
node_id: None,
distance: 1.0 - (r.score / 20.0).min(1.0),
metadata,
}
})
.collect())
}