Search a `MultiVectorStore` using budgeted MaxSim with optional PLAID candidate pruning. # Parameters `store` — the document collection. `plaid` — optional PLAID pruner (pass `None` to scan all docs). `query` — query Meta Token vectors (Matryoshka ordering). `budget` — number of leading query tokens to use; 0 falls back to all. `k` — number of top documents to return. `metric` — distance
(
store: &MultiVectorStore,
plaid: Option<&PlaidPruner>,
query: &[Vec<f32>],
budget: u8,
k: usize,
metric: DistanceMetric,
)
| 32 | /// # Returns |
| 33 | /// A `Vec<(doc_id, score)>` sorted descending by score, length ≤ `k`. |
| 34 | pub fn meta_embed_search( |
| 35 | store: &MultiVectorStore, |
| 36 | plaid: Option<&PlaidPruner>, |
| 37 | query: &[Vec<f32>], |
| 38 | budget: u8, |
| 39 | k: usize, |
| 40 | metric: DistanceMetric, |
| 41 | ) -> Vec<(u32, f32)> { |
| 42 | if k == 0 || query.is_empty() { |
| 43 | return Vec::new(); |
| 44 | } |
| 45 | |
| 46 | // Effective budget: 0 means use all query vectors. |
| 47 | let effective_budget = if budget == 0 { |
| 48 | query.len() as u8 |
| 49 | } else { |
| 50 | budget |
| 51 | }; |
| 52 | |
| 53 | // Determine candidate set. |
| 54 | let candidate_ids: Vec<u32> = match plaid { |
| 55 | Some(pruner) => pruner.candidates(query), |
| 56 | None => store.iter().map(|doc| doc.doc_id).collect(), |
| 57 | }; |
| 58 | |
| 59 | // Score each candidate. |
| 60 | let mut scored: Vec<(u32, f32)> = candidate_ids |
| 61 | .into_iter() |
| 62 | .filter_map(|doc_id| { |
| 63 | store.get(doc_id).map(|doc| { |
| 64 | let score = budgeted_maxsim(query, &doc.vectors, effective_budget, metric); |
| 65 | (doc_id, score) |
| 66 | }) |
| 67 | }) |
| 68 | .collect(); |
| 69 | |
| 70 | // Sort descending by score. |
| 71 | scored.sort_unstable_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal)); |
| 72 | scored.truncate(k); |
| 73 | scored |
| 74 | } |
| 75 | |
| 76 | // --------------------------------------------------------------------------- |
| 77 | // Tests |