1 | //! These types are not used for generating `Index`es. They are provided to help with |
2 | //! creating compatible JSON structures for configuring the JavaScript search |
3 | //! function. |
4 | //! |
5 | //! *Reference:* |
6 | //! <http://elasticlunr.com/docs/configuration.js.html> |
7 | |
8 | use std::collections::BTreeMap; |
9 | |
10 | /// Used to set the search configuration for a specific field. |
11 | /// When `expand` or `bool` is `None`, elasticlunr.js will use the value from |
12 | /// the global configuration. The `boost` field, if present, |
13 | /// increases the importance of this field when ordering search results. |
14 | #[derive (Serialize, Deserialize, Default, Debug, Copy, Clone, Eq, PartialEq)] |
15 | pub struct SearchOptionsField { |
16 | #[serde(skip_serializing_if = "Option::is_none" )] |
17 | pub boost: Option<u8>, |
18 | #[serde(skip_serializing_if = "Option::is_none" )] |
19 | pub bool: Option<SearchBool>, |
20 | #[serde(skip_serializing_if = "Option::is_none" )] |
21 | pub expand: Option<bool>, |
22 | } |
23 | |
24 | /// Sets which boolean model is used for searching with |
25 | /// multiple terms. Defaults to `Or`. |
26 | /// |
27 | /// - *AND* requires every search term to be present in results |
28 | /// - *OR* accepts results which have at least one term |
29 | /// |
30 | #[derive (Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq)] |
31 | #[serde(rename_all = "SCREAMING_SNAKE_CASE" )] |
32 | pub enum SearchBool { |
33 | Or, |
34 | And, |
35 | } |
36 | |
37 | impl Default for SearchBool { |
38 | fn default() -> Self { |
39 | SearchBool::Or |
40 | } |
41 | } |
42 | |
43 | /// The search configuration map which is passed to the |
44 | /// elasticlunr.js `Index.search()` function. |
45 | /// |
46 | /// |Key |Default| |
47 | /// |--------|-------| |
48 | /// |`bool` |`OR` | |
49 | /// |`expand`|`false`| |
50 | #[derive (Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)] |
51 | pub struct SearchOptions { |
52 | pub bool: SearchBool, |
53 | pub expand: bool, |
54 | pub fields: BTreeMap<String, SearchOptionsField>, |
55 | } |
56 | |
57 | #[cfg (test)] |
58 | mod tests { |
59 | use super::*; |
60 | use serde_json; |
61 | |
62 | #[test ] |
63 | fn test_normal_config() { |
64 | let options = SearchOptions { |
65 | fields: btreemap![ |
66 | "title" .into() => SearchOptionsField { |
67 | boost: Some(5), |
68 | ..Default::default() |
69 | }, |
70 | "body" .into() => SearchOptionsField { |
71 | boost: Some(1), |
72 | ..Default::default() |
73 | }, |
74 | ], |
75 | ..Default::default() |
76 | }; |
77 | let stringed = serde_json::to_string(&options).unwrap(); |
78 | |
79 | assert_eq!( |
80 | stringed, |
81 | r#"{"bool":"OR","expand":false,"fields":{"body":{"boost":1},"title":{"boost":5}}}"# |
82 | ); |
83 | } |
84 | |
85 | #[test ] |
86 | fn test_complex_config() { |
87 | let options = SearchOptions { |
88 | fields: btreemap! { |
89 | "title" .into() => SearchOptionsField { |
90 | expand: Some(true), |
91 | ..Default::default() |
92 | }, |
93 | "body" .into() => SearchOptionsField { |
94 | bool: Some(SearchBool::Or), |
95 | ..Default::default() |
96 | }, |
97 | "breadcrumbs" .into() => SearchOptionsField { |
98 | bool: Some(SearchBool::default()), |
99 | boost: Some(200), |
100 | ..Default::default() |
101 | }, |
102 | }, |
103 | expand: false, |
104 | bool: SearchBool::And, |
105 | }; |
106 | let stringed = serde_json::to_string_pretty(&options).unwrap(); |
107 | |
108 | assert_eq!( |
109 | stringed, |
110 | r#"{ |
111 | "bool": "AND", |
112 | "expand": false, |
113 | "fields": { |
114 | "body": { |
115 | "bool": "OR" |
116 | }, |
117 | "breadcrumbs": { |
118 | "boost": 200, |
119 | "bool": "OR" |
120 | }, |
121 | "title": { |
122 | "expand": true |
123 | } |
124 | } |
125 | }"# |
126 | ); |
127 | } |
128 | } |
129 | |