docling_rag/store/
memory.rs1use super::{top_k_by_cosine, VectorStore};
4use crate::model::{Chunk, Document, Scored};
5use crate::Result;
6use async_trait::async_trait;
7use std::sync::RwLock;
8
9#[derive(Default)]
11pub struct MemoryStore {
12 docs: RwLock<Vec<Document>>,
13 chunks: RwLock<Vec<Chunk>>,
14}
15
16impl MemoryStore {
17 pub fn new() -> Self {
19 MemoryStore::default()
20 }
21}
22
23#[async_trait]
24impl VectorStore for MemoryStore {
25 async fn migrate(&self) -> Result<()> {
26 Ok(())
27 }
28
29 async fn upsert_document(&self, doc: &Document) -> Result<()> {
30 let mut docs = self.docs.write().unwrap();
31 if let Some(existing) = docs.iter_mut().find(|d| d.id == doc.id) {
32 *existing = doc.clone();
33 } else {
34 docs.push(doc.clone());
35 }
36 Ok(())
37 }
38
39 async fn find_document_by_hash(&self, hash: &str) -> Result<Option<String>> {
40 Ok(self
41 .docs
42 .read()
43 .unwrap()
44 .iter()
45 .find(|d| d.hash == hash)
46 .map(|d| d.id.clone()))
47 }
48
49 async fn insert_chunks(&self, chunks: &[Chunk]) -> Result<()> {
50 self.chunks.write().unwrap().extend_from_slice(chunks);
51 Ok(())
52 }
53
54 async fn vector_search(&self, query: &[f32], k: usize) -> Result<Vec<Scored>> {
55 let chunks = self.chunks.read().unwrap();
56 let candidates = chunks.iter().filter_map(|c| {
57 c.embedding.as_ref().map(|e| {
58 let mut bare = c.clone();
59 bare.embedding = None;
60 (bare, e.clone())
61 })
62 });
63 Ok(top_k_by_cosine(query, candidates.collect::<Vec<_>>(), k))
64 }
65
66 async fn all_chunks(&self) -> Result<Vec<Chunk>> {
67 Ok(self
68 .chunks
69 .read()
70 .unwrap()
71 .iter()
72 .map(|c| {
73 let mut bare = c.clone();
74 bare.embedding = None;
75 bare
76 })
77 .collect())
78 }
79
80 async fn count_chunks(&self) -> Result<usize> {
81 Ok(self.chunks.read().unwrap().len())
82 }
83
84 async fn count_documents(&self) -> Result<usize> {
85 Ok(self.docs.read().unwrap().len())
86 }
87
88 async fn list_documents(&self) -> Result<Vec<Document>> {
89 Ok(self.docs.read().unwrap().clone())
90 }
91
92 async fn delete_document(&self, doc_id: &str) -> Result<()> {
93 self.docs.write().unwrap().retain(|d| d.id != doc_id);
94 self.chunks.write().unwrap().retain(|c| c.doc_id != doc_id);
95 Ok(())
96 }
97
98 async fn delete_documents_by_source(&self, source_uri: &str) -> Result<()> {
99 let ids: Vec<String> = {
100 let docs = self.docs.read().unwrap();
101 docs.iter()
102 .filter(|d| d.source_uri == source_uri)
103 .map(|d| d.id.clone())
104 .collect()
105 };
106 self.docs
107 .write()
108 .unwrap()
109 .retain(|d| d.source_uri != source_uri);
110 self.chunks
111 .write()
112 .unwrap()
113 .retain(|c| !ids.contains(&c.doc_id));
114 Ok(())
115 }
116
117 async fn clear(&self) -> Result<()> {
118 self.docs.write().unwrap().clear();
119 self.chunks.write().unwrap().clear();
120 Ok(())
121 }
122}