1use crate::mapping::field_type::FieldType;
2
3#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct FieldMapping {
15 pub name: String,
17 pub field_type: FieldType,
19 pub stored: bool,
21 pub indexed: bool,
23 pub doc_values: bool,
26 pub norms: bool,
29 pub analyzer: Option<String>,
31 pub search_analyzer: Option<String>,
34 pub parent_field: Option<String>,
38 pub copy_to: Vec<String>,
41}
42
43impl FieldMapping {
44 pub fn new(name: impl Into<String>, field_type: FieldType) -> Self {
54 let norms = field_type == FieldType::Text;
55 let is_vector = field_type.is_dense_vector();
56 let is_geo = matches!(field_type, FieldType::GeoPoint | FieldType::GeoShape);
57 let doc_values = !matches!(field_type, FieldType::Text) && !is_vector && !is_geo;
58
59 Self {
60 name: name.into(),
61 field_type,
62 stored: !is_vector && !is_geo, indexed: true,
64 doc_values,
65 norms,
66 analyzer: None,
67 search_analyzer: None,
68 parent_field: None,
69 copy_to: Vec::new(),
70 }
71 }
72
73 pub fn stored(mut self, stored: bool) -> Self {
75 self.stored = stored;
76 self
77 }
78
79 pub fn indexed(mut self, indexed: bool) -> Self {
81 self.indexed = indexed;
82 self
83 }
84
85 pub fn doc_values(mut self, doc_values: bool) -> Self {
87 self.doc_values = doc_values;
88 self
89 }
90
91 pub fn norms(mut self, norms: bool) -> Self {
93 self.norms = norms;
94 self
95 }
96
97 pub fn analyzer(mut self, analyzer: impl Into<String>) -> Self {
99 self.analyzer = Some(analyzer.into());
100 self
101 }
102
103 pub fn search_analyzer(mut self, analyzer: impl Into<String>) -> Self {
106 self.search_analyzer = Some(analyzer.into());
107 self
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn text_defaults() {
117 let m = FieldMapping::new("title", FieldType::Text);
118 assert!(m.stored);
119 assert!(m.indexed);
120 assert!(!m.doc_values);
121 assert!(m.norms);
122 assert!(m.analyzer.is_none());
123 }
124
125 #[test]
126 fn keyword_defaults() {
127 let m = FieldMapping::new("status", FieldType::Keyword);
128 assert!(m.stored);
129 assert!(m.indexed);
130 assert!(m.doc_values);
131 assert!(!m.norms);
132 }
133
134 #[test]
135 fn numeric_defaults() {
136 for ft in [
137 FieldType::Integer,
138 FieldType::Long,
139 FieldType::Float,
140 FieldType::Double,
141 ] {
142 let m = FieldMapping::new("val", ft);
143 assert!(m.stored);
144 assert!(m.indexed);
145 assert!(m.doc_values);
146 assert!(!m.norms);
147 }
148 }
149
150 #[test]
151 fn boolean_defaults() {
152 let m = FieldMapping::new("active", FieldType::Boolean);
153 assert!(m.doc_values);
154 assert!(!m.norms);
155 }
156
157 #[test]
158 fn date_defaults() {
159 let m = FieldMapping::new("created", FieldType::Date);
160 assert!(m.doc_values);
161 assert!(!m.norms);
162 }
163
164 #[test]
165 fn builder_chaining() {
166 let m = FieldMapping::new("body", FieldType::Text)
167 .stored(false)
168 .norms(false)
169 .analyzer("whitespace");
170 assert!(!m.stored);
171 assert!(!m.norms);
172 assert_eq!(m.analyzer.as_deref(), Some("whitespace"));
173 }
174}