elasticlunr/
config.rs

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
8use 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)]
15pub 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")]
32pub enum SearchBool {
33    Or,
34    And,
35}
36
37impl 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)]
51pub struct SearchOptions {
52    pub bool: SearchBool,
53    pub expand: bool,
54    pub fields: BTreeMap<String, SearchOptionsField>,
55}
56
57#[cfg(test)]
58mod 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}