summa_core/query/vector/
binary_dense.rs1use crate::dsl::Field;
4use crate::segment::SegmentReader;
5use std::sync::{Arc, Mutex};
6
7use super::VectorResultScorer;
8use super::combiner::MultiValueCombiner;
9use crate::query::traits::{CountFuture, Query, Scorer, ScorerFuture};
10
11#[derive(Debug, Clone)]
16pub struct BinaryDenseVectorQuery {
17 pub field: Field,
19 pub vector: Vec<u8>,
21 pub combiner: MultiValueCombiner,
23 probe_cache: Arc<Mutex<Option<crate::structures::IvfProbePlan>>>,
24 shared_vector: std::sync::OnceLock<Arc<[u8]>>,
28}
29
30impl std::fmt::Display for BinaryDenseVectorQuery {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 write!(
33 f,
34 "BinaryDense({}, bytes={})",
35 self.field.0,
36 self.vector.len(),
37 )
38 }
39}
40
41impl BinaryDenseVectorQuery {
42 pub fn new(field: Field, vector: Vec<u8>) -> Self {
43 Self {
44 field,
45 vector,
46 combiner: MultiValueCombiner::Max,
47 probe_cache: Arc::new(Mutex::new(None)),
48 shared_vector: std::sync::OnceLock::new(),
49 }
50 }
51
52 fn shared_vector(&self) -> Arc<[u8]> {
55 let shared = self
56 .shared_vector
57 .get_or_init(|| Arc::from(self.vector.as_slice()));
58 if shared.as_ref() == self.vector.as_slice() {
59 Arc::clone(shared)
60 } else {
61 Arc::from(self.vector.as_slice())
62 }
63 }
64
65 pub fn with_combiner(mut self, combiner: MultiValueCombiner) -> Self {
66 self.combiner = combiner;
67 self
68 }
69}
70
71impl Query for BinaryDenseVectorQuery {
72 fn candidate_query(&self) -> crate::Result<crate::query::CandidateQuery> {
73 Ok(crate::query::CandidateQuery::new(
74 self.field,
75 crate::query::candidate_scoring::ScoreComponent::Binary(self.vector.clone()),
76 )
77 .with_combiner(self.combiner))
78 }
79
80 fn scorer<'a>(&self, reader: &'a SegmentReader, limit: usize) -> ScorerFuture<'a> {
81 let field = self.field;
82 let vector = self.shared_vector();
83 let combiner = self.combiner;
84 let probe_cache = Arc::clone(&self.probe_cache);
85 Box::pin(async move {
86 let results = reader
87 .search_binary_dense_vector_with_probe_cache(
88 field,
89 &vector,
90 limit,
91 combiner,
92 &probe_cache,
93 )
94 .await?;
95
96 Ok(Box::new(VectorResultScorer::new(results, field.0)) as Box<dyn Scorer>)
97 })
98 }
99
100 #[cfg(feature = "sync")]
101 fn scorer_sync<'a>(
102 &self,
103 reader: &'a SegmentReader,
104 limit: usize,
105 ) -> crate::Result<Box<dyn Scorer + 'a>> {
106 let results = reader.search_binary_dense_vector_sync_with_probe_cache(
107 self.field,
108 &self.vector,
109 limit,
110 self.combiner,
111 &self.probe_cache,
112 )?;
113 Ok(Box::new(VectorResultScorer::new(results, self.field.0)) as Box<dyn Scorer>)
114 }
115
116 fn count_estimate<'a>(&self, _reader: &'a SegmentReader) -> CountFuture<'a> {
117 Box::pin(async move { Ok(u32::MAX) })
118 }
119}