milli_core/
external_documents_ids.rs

1use std::collections::HashMap;
2
3use heed::types::Str;
4use heed::{Database, RoIter, RoTxn, RwTxn};
5
6use crate::{DocumentId, BEU32};
7
8pub enum DocumentOperationKind {
9    Create,
10    Delete,
11}
12
13pub struct DocumentOperation {
14    pub external_id: String,
15    pub internal_id: DocumentId,
16    pub kind: DocumentOperationKind,
17}
18
19pub struct ExternalDocumentsIds(Database<Str, BEU32>);
20
21impl ExternalDocumentsIds {
22    pub fn new(db: Database<Str, BEU32>) -> ExternalDocumentsIds {
23        ExternalDocumentsIds(db)
24    }
25
26    /// Returns `true` if hard and soft external documents lists are empty.
27    pub fn is_empty(&self, rtxn: &RoTxn<'_>) -> heed::Result<bool> {
28        self.0.is_empty(rtxn)
29    }
30
31    pub fn get<A: AsRef<str>>(
32        &self,
33        rtxn: &RoTxn<'_>,
34        external_id: A,
35    ) -> heed::Result<Option<u32>> {
36        self.0.get(rtxn, external_id.as_ref())
37    }
38
39    /// An helper function to debug this type, returns an `HashMap` of both,
40    /// soft and hard fst maps, combined.
41    pub fn to_hash_map(&self, rtxn: &RoTxn<'_>) -> heed::Result<HashMap<String, u32>> {
42        let mut map = HashMap::default();
43        for result in self.0.iter(rtxn)? {
44            let (external, internal) = result?;
45            map.insert(external.to_owned(), internal);
46        }
47        Ok(map)
48    }
49
50    /// Applies the list of operations passed as argument, modifying the current external to internal id mapping.
51    ///
52    /// If the list contains multiple operations on the same external id, then the result is unspecified.
53    ///
54    /// # Panics
55    ///
56    /// - If attempting to delete a document that doesn't exist
57    /// - If attempting to create a document that already exists
58    pub fn apply(
59        &self,
60        wtxn: &mut RwTxn<'_>,
61        operations: Vec<DocumentOperation>,
62    ) -> heed::Result<()> {
63        for DocumentOperation { external_id, internal_id, kind } in operations {
64            match kind {
65                DocumentOperationKind::Create => {
66                    self.0.put(wtxn, &external_id, &internal_id)?;
67                }
68                DocumentOperationKind::Delete => {
69                    if !self.0.delete(wtxn, &external_id)? {
70                        panic!("Attempting to delete a non-existing document")
71                    }
72                }
73            }
74        }
75
76        Ok(())
77    }
78
79    /// Returns an iterator over all the external ids.
80    pub fn iter<'t>(&self, rtxn: &'t RoTxn<'_>) -> heed::Result<RoIter<'t, Str, BEU32>> {
81        self.0.iter(rtxn)
82    }
83}