1use nodedb_types::Surrogate;
9
10#[derive(
15 serde::Serialize,
16 serde::Deserialize,
17 zerompk::ToMessagePack,
18 zerompk::FromMessagePack,
19 Clone,
20 Debug,
21)]
22pub struct Posting {
23 pub doc_id: Surrogate,
24 pub term_freq: u32,
25 pub positions: Vec<u32>,
26}
27
28#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
30#[non_exhaustive]
31pub enum QueryMode {
32 #[default]
34 And,
35 Or,
37}
38
39impl From<nodedb_types::text_search::QueryMode> for QueryMode {
40 fn from(mode: nodedb_types::text_search::QueryMode) -> Self {
41 match mode {
42 nodedb_types::text_search::QueryMode::And => Self::And,
43 nodedb_types::text_search::QueryMode::Or => Self::Or,
44 }
45 }
46}
47
48#[derive(Debug, Clone)]
50pub struct TextSearchResult {
51 pub doc_id: Surrogate,
52 pub score: f32,
53 pub fuzzy: bool,
55}
56
57#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct MatchOffset {
60 pub start: usize,
61 pub end: usize,
62 pub term: String,
63}
64
65#[derive(Debug, Clone, Copy)]
67pub struct Bm25Params {
68 pub k1: f32,
70 pub b: f32,
72}
73
74impl Default for Bm25Params {
75 fn default() -> Self {
76 Self { k1: 1.2, b: 0.75 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn default_query_mode_is_and() {
86 assert_eq!(QueryMode::default(), QueryMode::And);
87 }
88
89 #[test]
90 fn public_query_mode_maps_to_the_same_mode() {
91 use nodedb_types::text_search::QueryMode as Public;
92 assert_eq!(QueryMode::from(Public::And), QueryMode::And);
93 assert_eq!(QueryMode::from(Public::Or), QueryMode::Or);
94 }
95
96 #[test]
97 fn default_bm25_params() {
98 let p = Bm25Params::default();
99 assert!((p.k1 - 1.2).abs() < f32::EPSILON);
100 assert!((p.b - 0.75).abs() < f32::EPSILON);
101 }
102
103 #[test]
104 fn posting_fields() {
105 let posting = Posting {
106 doc_id: Surrogate(1),
107 term_freq: 3,
108 positions: vec![0, 5, 12],
109 };
110 assert_eq!(posting.doc_id, Surrogate(1));
111 assert_eq!(posting.term_freq, 3);
112 assert_eq!(posting.positions, vec![0, 5, 12]);
113 }
114}