uqa_storage/hnsw_index/
canonical.rs1use super::HNSWIndex;
10use crate::{
11 read_control::StorageReadControl,
12 vector_index::{copy_vector, ordinal_count, VectorRead},
13 StorageBackendResult,
14};
15use std::ops::Bound::{Excluded, Unbounded};
16use uqa_core::{memory::BudgetedVec, DocId};
17
18impl VectorRead for HNSWIndex {
19 fn check_control(&self, control: &StorageReadControl) -> StorageBackendResult<()> {
20 control.check()
21 }
22 fn dimensions(&self) -> u32 {
23 self.dimensions
24 }
25 fn next_document_after(
26 &self,
27 after: Option<DocId>,
28 control: &StorageReadControl,
29 ) -> StorageBackendResult<Option<DocId>> {
30 control.check()?;
31 Ok(self
32 .active
33 .range((
34 after.map_or(Unbounded, |document| Excluded((document, u32::MAX))),
35 Unbounded,
36 ))
37 .next()
38 .map(|(key, _)| key.0))
39 }
40 fn document_vector_count(
41 &self,
42 document: DocId,
43 control: &StorageReadControl,
44 ) -> StorageBackendResult<u64> {
45 ordinal_count(
46 self.active
47 .range((document, 0)..=(document, u32::MAX))
48 .map(|(key, _)| key.1),
49 control,
50 )
51 }
52 fn read_vector(
53 &self,
54 document: DocId,
55 ordinal: u32,
56 control: &StorageReadControl,
57 ) -> StorageBackendResult<Option<BudgetedVec<f32>>> {
58 control.check()?;
59 let Some(node) = self.active.get(&(document, ordinal)) else {
60 return Ok(None);
61 };
62 let node = self
63 .nodes
64 .get(node)
65 .filter(|node| {
66 !node.deleted && node.doc_id == document && node.vector_ordinal == ordinal
67 })
68 .ok_or_else(|| {
69 crate::mvcc::VersionError::InvalidEncoding(
70 "HNSW canonical identity has no active raw vector",
71 )
72 .into_storage_error()
73 })?;
74 copy_vector(&node.raw_vector, control).map(Some)
75 }
76}