use crate::{BM25Params, ScoringMode};
use std::collections::BTreeSet;
use uqa_core::IndexStats;
use uqa_storage::{InvertedIndex, StorageBackendResult, TokenTermKey, DEFAULT_BLOCK_SIZE};
pub(super) fn search_stats_for_terms(
index: &dyn InvertedIndex,
field: &str,
terms: &[TokenTermKey],
doc_freqs: &[u64],
) -> StorageBackendResult<IndexStats> {
let mut stats = index.field_stats_scalar(field)?;
let mut seen = BTreeSet::<&TokenTermKey>::new();
for (term, doc_freq) in terms.iter().zip(doc_freqs) {
if seen.insert(term) {
stats.set_doc_freq_utf16(field.to_string(), term.to_term().into_utf16(), *doc_freq);
}
}
Ok(stats)
}
pub(super) fn raw_bm25_params(mode: &ScoringMode) -> BM25Params {
match mode {
ScoringMode::BM25(params) => *params,
ScoringMode::BayesianBM25(params) => params.bm25,
}
}
pub(super) fn block_max_scorer_fingerprint(params: BM25Params, stats: &IndexStats) -> String {
format!(
"bm25-block-v1:block={DEFAULT_BLOCK_SIZE}:k1={:016x}:b={:016x}:boost={:016x}:docs={}:avgdl={:016x}",
params.k1.to_bits(),
params.b.to_bits(),
params.boost.to_bits(),
stats.total_docs,
stats.avg_doc_length.to_bits(),
)
}