nodedb_fts/index/
fieldnorm.rs1use crate::backend::FtsBackend;
8use crate::codec::smallfloat;
9use crate::index::FtsIndex;
10
11impl<B: FtsBackend> FtsIndex<B> {
12 pub fn read_fieldnorm(&self, collection: &str, doc_id: u32) -> Result<Option<u32>, B::Error> {
16 let meta_key = format!("{collection}:fieldnorms");
17 let data = self.backend.read_meta(&meta_key)?;
18 match data {
19 Some(bytes) if (doc_id as usize) < bytes.len() => {
20 Ok(Some(smallfloat::decode(bytes[doc_id as usize])))
21 }
22 _ => Ok(None),
23 }
24 }
25
26 pub fn write_fieldnorm(
28 &self,
29 collection: &str,
30 doc_id: u32,
31 doc_length: u32,
32 ) -> Result<(), B::Error> {
33 let meta_key = format!("{collection}:fieldnorms");
34 let mut data = self.backend.read_meta(&meta_key)?.unwrap_or_default();
35
36 let idx = doc_id as usize;
37 if idx >= data.len() {
38 data.resize(idx + 1, 0);
39 }
40 data[idx] = smallfloat::encode(doc_length);
41
42 self.backend.write_meta(&meta_key, &data)
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use crate::backend::memory::MemoryBackend;
49 use crate::codec::smallfloat;
50 use crate::index::FtsIndex;
51
52 #[test]
53 fn fieldnorm_roundtrip() {
54 let idx = FtsIndex::new(MemoryBackend::new());
55 idx.write_fieldnorm("col", 0, 100).unwrap();
56 idx.write_fieldnorm("col", 5, 50).unwrap();
57
58 let norm0 = idx.read_fieldnorm("col", 0).unwrap().unwrap();
59 let norm5 = idx.read_fieldnorm("col", 5).unwrap().unwrap();
60
61 assert!(norm0 <= 100);
63 assert!(norm5 <= 50);
64 assert_eq!(norm0, smallfloat::decode(smallfloat::encode(100)));
65 assert_eq!(norm5, smallfloat::decode(smallfloat::encode(50)));
66 }
67
68 #[test]
69 fn fieldnorm_missing_doc() {
70 let idx = FtsIndex::new(MemoryBackend::new());
71 assert_eq!(idx.read_fieldnorm("col", 99).unwrap(), None);
72 }
73
74 #[test]
75 fn fieldnorm_overwrite() {
76 let idx = FtsIndex::new(MemoryBackend::new());
77 idx.write_fieldnorm("col", 0, 100).unwrap();
78 idx.write_fieldnorm("col", 0, 200).unwrap();
79
80 let norm = idx.read_fieldnorm("col", 0).unwrap().unwrap();
81 assert_eq!(norm, smallfloat::decode(smallfloat::encode(200)));
82 }
83}