1use std::collections::{HashMap, BTreeMap, HashSet};
2use std::convert::TryFrom;
3use std::ops::{Deref, DerefMut};
4use std::fmt;
5use std::hash::{Hash, Hasher};
6
7use tantivy::schema::{Schema, Field, TextOptions, IntOptions, IndexRecordOption};
8use tantivy::{Index, IndexReader, IndexWriter, Document, Term, DocAddress};
9use tantivy::query::{QueryParser, TermQuery};
10use tantivy::collector::{TopDocs};
11use tantivy::schema::Value as SchemaValue;
12
13
14use crate::prelude::*;
15use crate::prelude::join;
16
17use serde::{Serialize};
18use serde::de::DeserializeOwned;
19use std::fmt::{Debug, Display};
20
21
22#[derive(Clone, Eq, PartialEq)]
23pub enum SurferFieldTypes {
24 U64,
25 I64,
26 F64,
27 String,
28 Bytes,
29}
30
31#[derive(Clone, Eq, PartialEq)]
32pub struct SurferSchema {
33 schema: Schema,
34 mappings: HashMap<String, SurferFieldTypes>,
35 track_tf: bool,
36 track_tf_idf: bool,
37}
38
39impl SurferSchema {
40 pub fn new(schema: Schema, mappings: HashMap<String, SurferFieldTypes>, track_tf: bool, track_tf_idf: bool) -> Self {
41 Self {
42 schema,
43 mappings,
44 track_tf,
45 track_tf_idf,
46 }
47 }
48 pub fn resolve_mapping(&self) -> &HashMap<String, SurferFieldTypes> {
49 &self.mappings
50 }
51}
52
53impl Deref for SurferSchema {
54 type Target = Schema;
55 fn deref(&self) -> &Self::Target {
56 &self.schema
57 }
58}
59
60impl DerefMut for SurferSchema {
61 fn deref_mut(&mut self) -> &mut Self::Target {
62 &mut self.schema
63 }
64}
65
66impl fmt::Debug for SurferSchema {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 let itr = self.schema.fields();
69 let mut fields = Vec::new();
70 for (field, entry) in itr {
71 let debug = format!("Index: {} Name: {} Type: {:?}", field.field_id(), entry.name(), entry.field_type().value_type());
72 fields.push(debug);
73 };
74 write!(f, "{:?}", fields)
75 }
76}
77
78impl fmt::Display for SurferSchema {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 let itr = self.schema.fields();
81 for (_, entry) in itr {
82 let debug = format!("Name: {} Type: {:?}\n", entry.name(), entry.field_type().value_type());
83 let _ = write!(f, "{}", debug);
84 };
85 write!(f, "\n")
86 }
87}
88
89
90#[derive(Debug, Clone, Eq, PartialEq)]
92pub struct SurferBuilder {
93 schemas: HashMap<String, SurferSchema>,
94 home: Option<String>,
95}
96
97impl fmt::Display for SurferBuilder {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 let home = self.home.as_ref();
100 let indexes = &self.schemas;
101 for (name, schema) in indexes {
102 let home = resolve_index_directory_path(name, home);
103 let home = match home {
104 Ok(h) => h.to_string_lossy().to_string(),
105 Err(e) => format!("<PathError {}>", e.to_string())
106 };
107 let _ = write!(f, "Index: {} Location: {}\n", name, home);
108 let _ = write!(f, "{}", schema);
109 }
110 write!(f, "\n")
111 }
112}
113
114#[derive(Serialize)]
115struct SingleValuedNamedFieldDocument<'a>(BTreeMap<&'a str, &'a SchemaValue>);
116
117impl Default for SurferBuilder {
119 fn default() -> Self {
120 let schemas = HashMap::new();
121 let home = None;
122 Self {
123 schemas,
124 home,
125 }
126 }
127}
128
129
130impl SurferBuilder {
132 pub fn resolve_schemas(&self) -> &HashMap<String, SurferSchema> {
134 &self.schemas
135 }
136 pub fn set_home(&mut self, home: &str) {
138 self.home = Some(home.to_string());
139 }
140 pub fn add_schema(&mut self, name: String, schema: SurferSchema) {
142 self.schemas.insert(name, schema);
143 }
144 fn add_serde<T: Serialize>(&mut self, name: String, data: &T) {
146 let (schema, mappings) = to_schema(data, None).unwrap();
147 let schema = SurferSchema::new(schema, mappings, false, false);
148 self.schemas.insert(name, schema);
149 }
150 pub fn add_struct<T: Serialize>(&mut self, name: String, data: &T) {
152 self.add_serde::<T>(name, data);
153 }
154}
155
156#[derive(Debug, Clone, Eq, PartialEq)]
157pub struct AndCondition {
158 field_name: String,
159 field_value: String,
160}
161
162impl AndCondition {
163 pub fn new(field_name: String, field_value: String) -> Self {
164 Self {
165 field_name,
166 field_value,
167 }
168 }
169 pub fn update_field_value(&mut self, field_value: String) {
170 self.field_value = field_value;
171 }
172 pub fn resolve_field_name(&self) -> &String {
173 &self.field_name
174 }
175 pub fn resolve_field_value(&self) -> &String {
176 &self.field_value
177 }
178}
179
180#[derive(Debug, Clone, Eq, PartialEq)]
181pub struct OrCondition {
182 conditions: Vec<AndCondition>,
183}
184
185impl Display for OrCondition {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
187 let mut fragments = Vec::<String>::new();
188 for (index, condition) in self.conditions.iter().enumerate() {
189 if index == 0 {
190 let fragment = format!("{} = {}", condition.resolve_field_name(), condition.resolve_field_value());
191 fragments.push(fragment);
192 }
193 }
194 let x = fragments.join::<&str>(" AND ");
195 write!(f, "{}", x)
196 }
197}
198
199impl OrCondition {
200 pub fn new(conditions: Vec<AndCondition>) -> Self {
201 Self {
202 conditions
203 }
204 }
205 pub fn resolve_conditions_for_edit(&mut self) -> &mut Vec<AndCondition> {
206 &mut self.conditions
207 }
208 pub fn resolve_conditions(&self) -> &Vec<AndCondition> {
209 &self.conditions
210 }
211}
212
213
214impl From<(String, String)> for OrCondition {
215 fn from((field_name, field_value): (String, String)) -> Self {
216 let conditions = vec![AndCondition::new(field_name, field_value)];
217 Self::new(conditions)
218 }
219}
220
221pub struct Surf {
223 surfer: Surfer
224}
225
226impl Surf {
227 pub fn new(surfer: Surfer) -> Self {
228 Self {
229 surfer,
230 }
231 }
232 pub fn apply<T: Serialize + DeserializeOwned>(&mut self, index_name: &str, conditions: &Vec<OrCondition>, limit: Option<usize>, score: Option<f32>) -> Result<Option<Vec<T>>, IndexError> {
234 self.surfer.multiple_structs_by_field(index_name, conditions, limit, score)
235 }
236 pub fn select<T: Serialize + DeserializeOwned>(&mut self, index_name: &str, conditions: &Vec<OrCondition>) -> Result<Option<Vec<T>>, IndexError> {
238 let limit = Some(100usize);
239 let score = Some(0f32);
240 self.apply(index_name, conditions, limit, score)
241 }
242 pub fn insert<T: Serialize>(&mut self, name: &str, payload: &Vec<T>) -> Result<(), IndexError> {
244 self.surfer.insert_structs::<T>(name, payload)
245 }
246 pub fn delete(&mut self, index_name: &str, field_name: &str, field_value: &str) -> Result<(), IndexError> {
248 self.surfer.delete_structs_by_field(index_name, field_name, field_value)
249 }
250}
251
252impl Deref for Surf {
253 type Target = Surfer;
254 fn deref(&self) -> &Self::Target {
255 &self.surfer
256 }
257}
258
259impl DerefMut for Surf {
260 fn deref_mut(&mut self) -> &mut Self::Target {
261 &mut self.surfer
262 }
263}
264
265impl From<Surfer> for Surf {
266 fn from(surfer: Surfer) -> Self {
267 Self::new(surfer)
268 }
269}
270
271impl TryFrom<SurferBuilder> for Surf {
272 type Error = IndexError;
273 fn try_from(builder: SurferBuilder) -> Result<Self, Self::Error> {
274 let surfer = Surfer::try_from(builder)?;
275 Ok(Surf::from(surfer))
276 }
277}
278
279pub struct Surfer {
281 home: String,
282 indexes: HashMap<String, Index>,
283 fields: HashMap<String, Vec<Field>>,
284 readers: HashMap<String, Option<IndexReader>>,
285 writers: HashMap<String, Option<IndexWriter>>,
286 schemas: HashMap<String, SurferSchema>,
287}
288
289impl Surfer {
290 pub fn resolve_schema(&self, name: &str) -> Option<&SurferSchema> {
292 self.schemas.get(name)
293 }
294 pub fn home(&self) -> &String {
296 &self.home
297 }
298 pub fn which_index(&self, name: &str) -> Option<String> {
300 if !self.indexes.contains_key(name) {
301 return None;
302 }
303 if name.starts_with(&self.home) {
304 Some(name.to_string())
305 } else {
306 join(&self.home, name)
307 }
308 }
309 pub fn resolve_index(&self, name: &str) -> Option<&Index> {
311 if !self.indexes.contains_key(name) {
312 return None;
313 }
314 self.indexes.get(name)
315 }
316 pub fn insert_struct<T: Serialize>(&mut self, name: &str, data: &T) -> Result<(), IndexError> {
318 let data = serde_json::to_string(data)?;
319 let writer = self.writers.get(name);
320 if writer.is_none() {
321 return Ok(());
322 };
323
324 let index = self.indexes.get(name).unwrap();
325 let schema = &index.schema();
326
327 let writer = writer.unwrap();
328 if writer.is_none() {
329 let writer = open_index_writer(index)?;
330 self.writers.insert(name.to_string(), Some(writer));
331 };
332
333 let writer = self.writers.get_mut(name).unwrap().as_mut().unwrap();
334 let document = schema.parse_document(&data)?;
335 writer.add_document(document);
336 writer.commit()?;
337 Ok(())
338 }
339 pub fn insert_structs<T: Serialize>(&mut self, name: &str, payload: &Vec<T>) -> Result<(), IndexError> {
341 {
342 let result = self._prepare_index_writer(name);
343 if result.is_err() {
344 return Ok(());
345 };
346 }
347
348 let writer = self.writers.get_mut(name).unwrap().as_mut().unwrap();
349
350 let index = self.indexes.get(name).unwrap();
351 let schema = &index.schema();
352 for data in payload {
353 let data = serde_json::to_string(data)?;
354 let document = schema.parse_document(&data)?;
355 writer.add_document(document);
356 }
357
358 writer.commit()?;
359 Ok(())
360 }
361 fn jsonify(&self, name: &str, document: &Document) -> Result<String, IndexError> {
363 let schema = self.indexes.get(name).unwrap().schema();
364
365 let mut field_map = BTreeMap::new();
366 for (field, field_values) in document.get_sorted_field_values() {
367 let field_name = schema.get_field_name(field);
368 let fv = field_values.get(0);
369 if fv.is_none() {
370 let message = format!("Unable to jsonify: {}", name);
371 let reason = format!("Field: {} does not have any value", field_name);
372 let error = IndexError::new(message, reason);
373 return Err(error);
374 };
375 let fv = fv.unwrap().value();
376 field_map.insert(field_name, fv);
377 };
378 let payload = SingleValuedNamedFieldDocument(field_map);
379 let result = serde_json::to_string(&payload)
380 .map_err(|e| {
381 let message = "Unable to serialize struct".to_string();
382 let reason = e.to_string();
383 IndexError::new(
384 message,
385 reason,
386 )
387 });
388 result
389 }
390 fn _is_index_valid(&self, name: &str) -> bool {
391 let index = self.indexes.get(name);
392 if index.is_some() {
393 true
394 } else {
395 false
396 }
397 }
398 fn _is_reader_valid(&self, name: &str) -> bool {
399 if !self.readers.contains_key(name) {
400 return false;
401 }
402 let reader = self.readers.get(name).unwrap();
403 if reader.is_some() {
404 true
405 } else {
406 false
407 }
408 }
409 fn _is_writer_valid(&self, name: &str) -> bool {
410 if !self.writers.contains_key(name) {
411 return false;
412 }
413 let writer = self.writers.get(name).unwrap();
414 if writer.is_some() {
415 true
416 } else {
417 false
418 }
419 }
420 fn _prepare_index_writer(&mut self, index_name: &str) -> Result<(), IndexError> {
421 if !self._is_index_valid(index_name) {
422 let message = format!("Unable to prepare the writer");
423 let reason = format!("Index was missing: {} ", index_name);
424 return Err(IndexError::new(message, reason));
425 };
426 if self._is_writer_valid(&index_name) {
427 return Ok(());
428 };
429 let index = self.indexes.get(index_name).unwrap();
430 let writer = open_index_writer(index)?;
431 let _ = self.writers.insert(index_name.to_string(), Some(writer));
432 Ok(())
433 }
434
435 fn _prepare_index_reader(&mut self, index_name: &str) -> Result<(), IndexError> {
436 if !self._is_index_valid(index_name) {
437 let message = format!("Unable to prepare the reader");
438 let reason = format!("Index was missing: {} ", index_name);
439 return Err(IndexError::new(message, reason));
440 };
441 if self._is_reader_valid(&index_name) {
442 return Ok(());
443 };
444 let index = self.indexes.get(index_name).unwrap();
445 let reader = open_index_reader(index)?;
446 let _ = self.readers.insert(index_name.to_string(), Some(reader));
447 Ok(())
448 }
449 fn _build_terms(&self, schema: &SurferSchema, field_value: &str) -> Result<Vec<Term>, IndexError> {
450 let mut field_names = Vec::<&String>::with_capacity(schema.mappings.len());
451 for (field_name, field_type) in schema.mappings.iter() {
452 match field_type {
453 SurferFieldTypes::String => field_names.push(field_name),
454 _ => {}
455 };
456 }
457 let mut terms = Vec::<Term>::with_capacity(schema.mappings.len());
458 if field_names.is_empty() {
459 return Ok(terms);
460 };
461 for field_name in field_names {
462 let term = self._build_term(schema, field_name, field_value)?;
463 terms.push(term);
464 }
465 Ok(terms)
466 }
467 fn _build_term(&self, schema: &SurferSchema, field_name: &str, field_value: &str) -> Result<Term, IndexError> {
468 let mappings = schema.resolve_mapping();
469
470 let field_type = mappings.get(field_name);
471 if field_type.is_none() {
472 let message = format!("Unable to perform search");
473 let reason = format!("Missing field: {}", field_name);
474 return Err(IndexError::new(message, reason));
475 };
476 let field_type = field_type.unwrap();
477
478 let field = schema.get_field(field_name);
479 if field.is_none() {
480 let message = format!("Unable to perform search");
481 let reason = format!("Missing field: {}", field_name);
482 return Err(IndexError::new(message, reason));
483 };
484 let field = field.unwrap();
485
486 let term = match field_type {
487 SurferFieldTypes::U64 => {
488 let field_value = field_value.parse::<u64>().map_err(|e| {
489 let message = format!("Invalid search: {}", field_value);
490 let reason = e.to_string();
491 IndexError::new(message, reason)
492 })?;
493 Term::from_field_u64(field, field_value)
494 }
495 SurferFieldTypes::I64 => {
496 let field_value = field_value.parse::<i64>().map_err(|e| {
497 let message = format!("Invalid search: {}", field_value);
498 let reason = e.to_string();
499 IndexError::new(message, reason)
500 })?;
501 Term::from_field_i64(field, field_value)
502 }
503 SurferFieldTypes::F64 => {
504 let field_value = field_value.parse::<f64>().map_err(|e| {
505 let message = format!("Invalid search: {}", field_value);
506 let reason = e.to_string();
507 IndexError::new(message, reason)
508 })?;
509 Term::from_field_f64(field, field_value)
510 }
511 SurferFieldTypes::String => {
512 Term::from_field_text(field, field_value)
513 }
514 SurferFieldTypes::Bytes => {
515 let message = format!("Invalid search: {}", field_value);
516 let reason = "Cant search on bytes".to_string();
517 return Err(IndexError::new(message, reason));
518 }
519 };
520
521 Ok(term)
522 }
523
524 fn _build_term_query(&self, term: Term, segment_postings_options: Option<IndexRecordOption>) -> Result<TermQuery, IndexError> {
525 let segment_postings_options = match segment_postings_options {
526 Some(option) => option,
527 None => IndexRecordOption::Basic,
528 };
529 Ok(TermQuery::new(term, segment_postings_options))
530 }
531
532 fn _resolve_surfer_schema(&self, index_name: &str) -> Result<&SurferSchema, IndexError> {
533 let schema = self.schemas.get(index_name);
534 if schema.is_none() {
535 let message = format!("Invalid index operation for {}", index_name);
536 let reason = format!("No schema found for index: {}", index_name);
537 return Err(IndexError::new(message, reason));
538 };
539 let schema = schema.unwrap();
540 Ok(schema)
541 }
542
543 fn _resolve_limit(&self, limit: Option<usize>) -> usize {
544 match limit {
545 Some(limit) => limit,
546 None => 10
547 }
548 }
549
550 fn _resolve_score(&self, score: Option<f32>) -> f32 {
551 match score {
552 Some(score) => score,
553 None => 90f32
554 }
555 }
556
557 pub fn delete_structs_by_field(&mut self, index_name: &str, field_name: &str, field_value: &str) -> Result<(), IndexError> {
559 let schema = self._resolve_surfer_schema(index_name)?;
560 let term = self._build_term(&schema, field_name, field_value)?;
561 let _ = self._prepare_index_writer(index_name)?;
562 let writer = self.writers.get_mut(index_name).unwrap().as_mut().unwrap();
563 let _ = writer.delete_term(term);
564 let _ = writer.commit()?;
565 Ok(())
566 }
567
568 pub fn delete_structs(&mut self, index_name: &str, field_value: &str) -> Result<(), IndexError> {
570 let schema = self._resolve_surfer_schema(index_name)?;
571 let terms = self._build_terms(&schema, field_value)?;
572 let _ = self._prepare_index_writer(index_name)?;
573 let writer = self.writers.get_mut(index_name).unwrap().as_mut().unwrap();
574 for i in 0..terms.len() {
575 let term = terms.get(i).unwrap().to_owned();
576 let _ = writer.delete_term(term);
577 }
578 let _ = writer.commit()?;
579 Ok(())
580 }
581
582 pub fn read_all_structs_by_field<T: Serialize + DeserializeOwned>(&mut self, index_name: &str, field_name: &str, field_value: &str) -> Result<Option<Vec<T>>, IndexError> {
584 self.read_structs_by_field::<T>(index_name, field_name, field_value, None, Some(0f32))
585 }
586 pub fn read_structs_by_field<T: Serialize + DeserializeOwned>(&mut self, index_name: &str, field_name: &str, field_value: &str, limit: Option<usize>, score: Option<f32>) -> Result<Option<Vec<T>>, IndexError> {
588 let conditions = vec![OrCondition::from((field_name.to_string(), field_value.to_string()))];
589 self.multiple_structs_by_field::<T>(index_name, &conditions, limit, score)
590 }
591
592 pub fn read_string(&mut self, name: &str, query: &str, limit: Option<usize>, score: Option<f32>) -> Result<Option<Vec<String>>, IndexError> {
594 {
595 let result = self._prepare_index_reader(name);
596 if result.is_err() {
597 return Ok(None);
598 };
599 }
600 let index = self.indexes.get(name).unwrap();
601 let reader = self.readers.get(name).unwrap().as_ref().unwrap();
602
603 let default_fields = self.fields.get(name).unwrap().clone();
604 let searcher = reader.searcher();
605
606 let query_parser = QueryParser::for_index(&index, default_fields);
607 let query = query_parser.parse_query(query)?;
608 let limit = if limit.is_some() {
609 limit.unwrap()
610 } else {
611 10
612 };
613 let top_docs = searcher.search(&query, &TopDocs::with_limit(limit))?;
614
615 let mut docs = Vec::with_capacity(top_docs.len());
616 for (doc_score, doc_address) in top_docs {
617 if score.is_some() && doc_score < score.unwrap() {
618 continue;
619 }
620 let doc = searcher.doc(doc_address)?;
621 let doc = self.jsonify(name, &doc)?;
622 docs.push(doc);
623 };
624 Ok(Some(docs))
625 }
626
627 pub fn read_all_structs<T: Serialize + DeserializeOwned>(&mut self, name: &str, query: &str) -> Result<Option<Vec<T>>, IndexError> {
629 self.read_structs(name, query, None, None)
630 }
631
632 pub fn read_structs<T: Serialize + DeserializeOwned>(&mut self, name: &str, query: &str, limit: Option<usize>, score: Option<f32>) -> Result<Option<Vec<T>>, IndexError> {
634 {
635 let result = self._prepare_index_reader(name);
636 if result.is_err() {
637 return Ok(None);
638 };
639 }
640 let index = self.indexes.get(name).unwrap();
641 let reader = self.readers.get(name).unwrap().as_ref().unwrap();
642
643 let surfer_schema = self.schemas.get(name).unwrap();
644 let mappings = surfer_schema.resolve_mapping();
645
646 let mut fields = Vec::<Field>::with_capacity(mappings.len());
647 for (f, fe) in surfer_schema.schema.fields() {
648 let name = fe.name();
649 if !mappings.contains_key(name) {
650 continue;
651 };
652 let ft = mappings.get(name).unwrap();
653 match ft {
654 SurferFieldTypes::String => fields.push(f),
655 _ => {}
656 }
657 };
658
659 let searcher = reader.searcher();
660
661 let query_parser = QueryParser::for_index(&index, fields);
662 let query = query_parser.parse_query(query)?;
663 let limit = if limit.is_some() {
664 limit.unwrap()
665 } else {
666 10
667 };
668 let top_docs = searcher.search(&query, &TopDocs::with_limit(limit))?;
669
670 let mut docs = Vec::with_capacity(top_docs.len());
671 for (doc_score, doc_address) in top_docs {
672 if score.is_some() && doc_score < score.unwrap() {
673 continue;
674 }
675 let doc = searcher.doc(doc_address)?;
676 let doc = self.jsonify(name, &doc)?;
677 let doc = serde_json::from_str::<T>(&doc).unwrap();
678 docs.push(doc);
679 };
680 Ok(Some(docs))
681 }
682 fn multiple_structs_by_field<T: Serialize + DeserializeOwned>(&mut self, index_name: &str, conditions: &Vec<OrCondition>, limit: Option<usize>, score: Option<f32>) -> Result<Option<Vec<T>>, IndexError> {
684 let _ = self._prepare_index_reader(index_name)?;
685 let reader = self.readers.get(index_name).unwrap().as_ref().unwrap();
686 let searcher = reader.searcher();
687 let limit = self._resolve_limit(limit);
688 let cutoff = self._resolve_score(score);
689 let schema = self._resolve_surfer_schema(index_name)?;
690 let mut all_docs = HashSet::<SurferDocAddress>::new();
691
692 for condition in conditions {
693 let and = condition.resolve_conditions();
694 let mut docs = HashSet::new();
695 for (i, c) in and.iter().enumerate() {
696 let field_name = c.resolve_field_name();
697 let field_value = c.resolve_field_value();
698 let term = self._build_term(schema, field_name, field_value)?;
699 let query = self._build_term_query(term, None)?;
700 let mut tmp = HashSet::new();
701 let top_docs = searcher
702 .search(&query, &TopDocs::with_limit(limit))
703 .map_err(|e| {
704 let message = "Error while term query".to_string();
705 let reason = e.to_string();
706 IndexError::new(message, reason)
707 })?;
708
709
710 for (score, address) in top_docs.to_owned() {
711 if score < cutoff {
712 continue;
713 };
714
715 let address = SurferDocAddress::from(address);
716 if i == 0 {
718 tmp.insert(address);
719 continue;
720 }
721
722 if docs.contains(&address) {
723 tmp.insert(address);
724 }
725 }
726
727 if tmp.is_empty() {
728 docs.clear();
729 break;
730 } else {
731 docs.extend(tmp);
732 }
733 }
734 all_docs.extend(docs);
735 };
736
737 let mut docs = Vec::with_capacity(all_docs.len());
738 for doc_address in all_docs {
739 let doc = searcher.doc(doc_address.0)?;
740 let doc = self.jsonify(index_name, &doc)?;
741 let doc = serde_json::from_str::<T>(&doc).unwrap();
742 docs.push(doc);
743 };
744 Ok(Some(docs))
745 }
746}
747
748impl Surfer {
750 pub fn new(builder: SurferBuilder) -> Self {
751 Surfer::try_from(builder).unwrap()
752 }
753}
754
755fn initialize_mmap(name: &str, home: &str, schema: &Schema) -> Result<Index, IndexError> {
757 let path = resolve_index_directory_path(name, Some(home))?;
758 if path.exists() {
759 let dir = open_mmap_directory(path)?;
760 open_index(dir, None)
761 } else {
762 let dir = open_mmap_directory(path)?;
763 open_index(dir, Some(&schema))
764 }
765}
766
767fn extract_home(builder: &SurferBuilder) -> Result<String, IndexError> {
769 let home = builder.home.as_ref();
770 let home = resolve_home(home)?;
771 Ok(home.to_str().unwrap().to_string())
772}
773
774fn initialized_index(home: &str, builder: &SurferBuilder) -> Result<HashMap<String, Index>, IndexError> {
776 let schemas = &builder.schemas;
777 let mut indexes = HashMap::<String, Index>::with_capacity(schemas.len());
778 for (name, schema) in schemas {
779 let index = initialize_mmap(name, &home, &schema)?;
780 indexes.insert(name.to_string(), index);
781 };
782 Ok(indexes)
783}
784
785fn extract_fields(builder: &SurferBuilder) -> HashMap<String, Vec<Field>> {
787 let data = &builder.schemas;
788 let mut fields = HashMap::<String, Vec<Field>>::with_capacity(data.len());
789 for (data, schema) in data {
790 let key = data.clone();
791 let value: Vec<Field> = schema.fields().map(|(f, _)| f).collect();
792 fields.insert(key, value);
793 };
794 fields
795}
796
797
798impl TryFrom<SurferBuilder> for Surfer {
799 type Error = IndexError;
800 fn try_from(builder: SurferBuilder) -> Result<Self, Self::Error> {
801 let home = extract_home(&builder)?;
802 let indexes = initialized_index(&home, &builder)?;
803 let fields = extract_fields(&builder);
804
805 let mut readers = HashMap::new();
806 let mut writers = HashMap::new();
807 for (name, _) in &builder.schemas {
808 let reader: Option<IndexReader> = None;
809 let writer: Option<IndexWriter> = None;
810 writers.insert(name.to_string(), writer);
811 readers.insert(name.to_string(), reader);
812 };
813 let schemas = builder.resolve_schemas().clone();
814 Ok(Surfer {
815 home,
816 indexes,
817 fields,
818 readers,
819 writers,
820 schemas,
821 })
822 }
823}
824
825struct SurferDocAddress(DocAddress);
826
827impl SurferDocAddress {
828 fn new(address: DocAddress) -> Self {
829 Self(address)
830 }
831}
832
833impl From<DocAddress> for SurferDocAddress {
834 fn from(address: DocAddress) -> Self {
835 Self::new(address)
836 }
837}
838
839
840impl Deref for SurferDocAddress {
841 type Target = DocAddress;
842
843 fn deref(&self) -> &Self::Target {
844 &self.0
845 }
846}
847
848impl DerefMut for SurferDocAddress {
849 fn deref_mut(&mut self) -> &mut Self::Target {
850 &mut self.0
851 }
852}
853
854impl Display for SurferDocAddress {
855 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
856 let address = &self.0;
857 write!(f, "SegmentLocalId = {}, DocId {})", address.0, address.1)
858 }
859}
860
861impl Debug for SurferDocAddress {
862 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
863 let address = &self.0;
864 write!(f, "SegmentLocalId = {}, DocId {})", address.0, address.1)
865 }
866}
867
868
869impl PartialEq for SurferDocAddress {
870 fn eq(&self, other: &SurferDocAddress) -> bool {
871 let doc_address = &self.0;
872 let other_doc_address = other.0;
873 doc_address.0 == other_doc_address.0 && doc_address.1 == other_doc_address.1
874 }
875}
876
877impl Hash for SurferDocAddress {
878 fn hash<H: Hasher>(&self, state: &mut H) {
879 let address = self.0;
880 state.write_u32(address.0);
881 state.write_u32(address.1);
882 state.finish();
883 }
884}
885
886impl Eq for SurferDocAddress {}
887
888pub enum Control {
890 ControlTextOptions(TextOptions),
891 ControlIntOptions(IntOptions),
892}
893
894
895#[cfg(test)]
896mod library_tests {
897 use super::*;
898 use super::super::utils;
899 use serde::{Serialize, Deserialize};
900 use std::fmt::Debug;
901 use std::path::Path;
902 use std::fs::remove_dir_all;
903 use std::cmp::{Ord, Ordering, Eq};
904 use std::collections::HashSet;
905 use std::iter::FromIterator;
906 use std::hash::{Hash, Hasher};
907
908
909 #[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
910 struct Giant {
911 a: String,
912 c: u64,
913 d: u32,
914 e: u16,
915 f: u8,
916 g: i64,
917 h: i32,
918 i: i16,
919 j: i8,
920 k: f64,
921 l: f32,
922
923 }
924
925 impl Default for Giant {
926 fn default() -> Self {
927 let a: String = "tag1".to_string();
928 let c: u64 = 10000;
929 let d: u32 = 1000;
930 let e: u16 = 100;
931 let f: u8 = 10;
932 let g: i64 = 20000;
933 let h: i32 = 2000;
934 let i: i16 = 200;
935 let j: i8 = 20;
936 let k: f64 = 10.0;
937 let l: f32 = 1.0;
938 Giant {
939 a,
940 c,
941 d,
942 e,
943 f,
944 g,
945 h,
946 i,
947 j,
948 k,
949 l,
950
951 }
952 }
953 }
954
955 #[test]
956 fn validate_giant() {
957 let name = random_string(None);
958 let home = ".validate_giant";
959 let index_path = format!("{}/{}", home, name);
960 let path = Path::new(&index_path);
961 assert!(!path.exists());
962
963 let giant = Giant::default();
964
965 let mut builder = SurferBuilder::default();
966 builder.set_home(home);
967 builder.add_struct("giant".to_string(), &giant);
968 let mut surfer = Surfer::try_from(builder).unwrap();
969 let data = vec![Giant::default()];
970 let computed = surfer.insert_structs("giant", &data);
971 assert!(computed.is_ok());
972 let a: String = "tag1".to_string();
973 let c: u64 = 10000;
974 let d: u32 = 1000;
975 let e: u16 = 100;
976 let f: u8 = 10;
977 let g: i64 = 20000;
978 let h: i32 = 2000;
979 let i: i16 = 200;
980 let j: i8 = 20;
981 let k: f64 = 10.0;
982 let l: f32 = 1.0;
983
984 let conditions = vec![
985 AndCondition::new("a".to_string(), format!("{}", a)),
986 AndCondition::new("c".to_string(), format!("{}", c)),
987 AndCondition::new("d".to_string(), format!("{}", d)),
988 AndCondition::new("e".to_string(), format!("{}", e)),
989 AndCondition::new("g".to_string(), format!("{}", g)),
990 AndCondition::new("f".to_string(), format!("{}", f)),
991 AndCondition::new("h".to_string(), format!("{}", h)),
992 AndCondition::new("i".to_string(), format!("{}", i)),
993 AndCondition::new("j".to_string(), format!("{}", j)),
994 AndCondition::new("k".to_string(), format!("{}", k)),
995 AndCondition::new("l".to_string(), format!("{}", l)),
996 ];
997 let conditions = vec![OrCondition::new(conditions)];
998 let computed = surfer.multiple_structs_by_field::<Giant>("giant", &conditions, None, Some(0.0));
999 assert!(computed.is_ok());
1000 let computed = computed.unwrap();
1001 assert!(computed.is_some());
1002 let computed = computed.unwrap();
1003 assert_eq!(computed, vec![Giant::default()]);
1004
1005 let computed = surfer.multiple_structs_by_field::<Giant>("giant", &conditions, None, None);
1006 assert!(computed.is_ok());
1007
1008
1009 let computed = surfer.delete_structs_by_field("giant", "c", "crap");
1010 assert!(computed.is_err());
1011
1012 let computed = surfer.delete_structs_by_field("giant", "c", "crap");
1013 assert!(computed.is_err());
1014
1015 let computed = surfer.delete_structs_by_field("giant", "g", "crap");
1016 assert!(computed.is_err());
1017
1018 let computed = surfer.delete_structs_by_field("giant", "k", "crap");
1019 assert!(computed.is_err());
1020
1021 let computed = surfer.delete_structs_by_field("giant", "crap", "crap");
1022 assert!(computed.is_err());
1023
1024 let computed = surfer.delete_structs_by_field("crap", "crap", "crap");
1025 assert!(computed.is_err());
1026
1027 let _ = remove_dir_all(index_path);
1028 let _ = remove_dir_all(home);
1029 }
1030
1031
1032 #[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
1033 struct OldMan {
1034 title: String,
1035 body: String,
1036 }
1037
1038 impl Default for OldMan {
1039 fn default() -> Self {
1040 let title = "".to_string();
1041 let body = "".to_string();
1042 Self {
1043 title,
1044 body,
1045 }
1046 }
1047 }
1048
1049 #[test]
1050 fn validate_read_existing_documents_as_structs() {
1051 let name = random_string(None);
1052 let home = ".validate_read_existing_documents_as_structs";
1053 let index_path = format!("{}/{}", home, name);
1054 let path = Path::new(&index_path);
1055 assert!(!path.exists());
1056
1057 let data = OldMan::default();
1058
1059 let mut builder = SurferBuilder::default();
1060 builder.set_home(home);
1061 builder.add_struct(name.clone(), &data);
1062
1063 {
1064 let title = "The Old Man and the Sea".to_string();
1065 let body = "He was an old man who fished alone in a skiff in the Gulf Stream and he had gone eighty-four days now without taking a fish.".to_string();
1066 let old_man_doc = OldMan {
1067 title,
1068 body,
1069 };
1070
1071 let mut surfer = Surfer::new(builder.clone());
1072 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1073 }
1074
1075 let mut surfer = Surfer::new(builder.clone());
1076 let query = "sea whale";
1077 let result = surfer.read_structs::<OldMan>(&name, query, None, None);
1078 assert!(result.is_ok());
1079 assert!(path.exists());
1080 let _ = remove_dir_all(index_path);
1081 let _ = remove_dir_all(home);
1082 }
1083
1084 #[test]
1085 fn validate_read_existing_documents_as_strings() {
1086 let title = "The Old Man and the Sea".to_string();
1087 let body = "He was an old man who fished alone in a skiff in the Gulf Stream and he had gone eighty-four days now without taking a fish.".to_string();
1088 let expected = OldMan {
1089 title,
1090 body,
1091 };
1092
1093
1094 let name = random_string(None);
1095 let mut builder = SurferBuilder::default();
1096 let data = OldMan::default();
1097 let home = ".validate_read_existing_documents_as_strings";
1098 let index_path = format!("{}/{}", home, name);
1099 let path = Path::new(&index_path);
1100 assert!(!path.exists());
1101 builder.set_home(home);
1102 builder.add_struct(name.to_string(), &data);
1103
1104 {
1105 let title = "The Old Man and the Sea".to_string();
1106 let body = "He was an old man who fished alone in a skiff in the Gulf Stream and he had gone eighty-four days now without taking a fish.".to_string();
1107 let old_man_doc = OldMan {
1108 title,
1109 body,
1110 };
1111
1112 let mut surfer = Surfer::new(builder.clone());
1113 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1114 }
1115
1116 let mut surfer = Surfer::new(builder.clone());
1117 let query = "sea whale";
1118 let result = surfer.read_string("Non-existent", query, None, None);
1119 assert!(result.is_ok());
1120 let result = result.unwrap();
1121 assert!(result.is_none());
1122 let result = surfer.read_string(&name, query, None, None);
1123 assert!(result.is_ok());
1124 let result = result.unwrap();
1125 assert!(result.is_some());
1126 let result = result.unwrap();
1127 let mut computed = Vec::new();
1128 for entry in result {
1129 let data: serde_json::Result<OldMan> = serde_json::from_str(&entry);
1130 let data = data.unwrap();
1131 computed.push(data);
1132 };
1133 assert_eq!(computed, vec![expected.clone()]);
1134
1135 let result = surfer.read_string(&name, query, None, None);
1137 assert!(result.is_ok());
1138 let result = result.unwrap();
1139 assert!(result.is_some());
1140 let result = result.unwrap();
1141 let mut computed = Vec::new();
1142 for entry in result {
1143 let data: serde_json::Result<OldMan> = serde_json::from_str(&entry);
1144 let data = data.unwrap();
1145 computed.push(data);
1146 };
1147 assert_eq!(computed, vec![expected.clone()]);
1148
1149 let _ = remove_dir_all(&index_path);
1150 let _ = remove_dir_all(home);
1151 }
1152
1153 #[test]
1154 fn validate_as_rust_structs() {
1155 let name = random_string(None);
1156 let home = ".validate_as_rust_structs".to_string();
1157 let index_path = format!("{}/{}", home, name);
1158 let path = Path::new(&index_path);
1159 assert!(!path.exists());
1160
1161 let title = "The Old Man and the Sea".to_string();
1162 let body = "He was an old man who fished alone in a skiff in the Gulf Stream and he had gone eighty-four days now without taking a fish.".to_string();
1163 let old_man_doc = OldMan {
1164 title,
1165 body,
1166 };
1167
1168
1169 let mut builder = SurferBuilder::default();
1170 builder.set_home(home.as_str());
1171 builder.add_struct(name.to_string(), &old_man_doc);
1172 let mut surfer = Surfer::new(builder);
1173
1174 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1175 let query = "sea whale";
1176
1177 let result = surfer.read_structs::<OldMan>("non-existent", query, None, None);
1178 assert!(result.is_ok());
1179 let result = result.unwrap();
1180 assert!(result.is_none());
1181
1182 let result = surfer.read_structs::<OldMan>(&name, query, None, None).unwrap().unwrap();
1183 for computed in result {
1184 assert_eq!(computed, old_man_doc);
1185 };
1186 assert!(path.exists());
1187
1188 let result = surfer.read_structs::<OldMan>(&name, query, None, None).unwrap().unwrap();
1191 for computed in result {
1192 assert_eq!(computed, old_man_doc);
1193 };
1194
1195
1196 let _ = remove_dir_all(index_path);
1197 let _ = remove_dir_all(home);
1198 }
1199
1200 #[test]
1201 fn validate_initialize_mmap() {
1202 let home = ".validate_initialize_mmap";
1203 let index_name = "someindex";
1204 let path_to_index = ".validate_initialize_mmap/someindex";
1205 let path = Path::new(path_to_index);
1206 assert!(!path.exists());
1207 let oldman = OldMan::default();
1208 let (schema, mappings) = to_schema(&oldman, None).unwrap();
1209 let schema = SurferSchema::new(schema, mappings, false, false);
1210 let _ = initialize_mmap(index_name, home, &schema);
1211 assert!(path.exists());
1212 let _ = std::fs::remove_dir_all(path_to_index);
1213
1214 let _ = remove_dir_all(path_to_index);
1215 let _ = remove_dir_all(index_name);
1216 let _ = remove_dir_all(home);
1217 }
1218
1219 #[test]
1220 fn validate_read_existing_documents_as_structs_limit_one() {
1221 let name = random_string(None);
1222 let home = ".validate_read_existing_documents_as_structs_limit_one";
1223 let index_path = format!("{}/{}", home, name);
1224 let path = Path::new(&index_path);
1225 assert!(!path.exists());
1226
1227 let data = OldMan::default();
1228
1229 let mut builder = SurferBuilder::default();
1230 builder.set_home(home);
1231 builder.add_struct(name.clone(), &data);
1232
1233 let title = "The Old Man and the Sea".to_string();
1234 let body = "He was an old man who fished alone in a skiff in the Gulf Stream and he had gone eighty-four days now without taking a fish.".to_string();
1235 let old_man_doc = OldMan {
1236 title,
1237 body,
1238 };
1239
1240 let mut surfer = Surfer::new(builder.clone());
1241 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1242 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1243 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1244 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1245 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1246
1247 let query = "sea whale";
1248 let result = surfer.read_structs::<OldMan>(&name, query, None, None);
1249 assert!(result.is_ok());
1250 let result = result.unwrap().unwrap();
1251 assert_eq!(result.len(), 5);
1252
1253 let result = surfer.read_structs::<OldMan>(&name, query, Some(1), None);
1254 assert!(result.is_ok());
1255 let result = result.unwrap().unwrap();
1256 assert_eq!(result.len(), 1);
1257
1258 assert!(path.exists());
1259 let _ = remove_dir_all(index_path);
1260 let _ = remove_dir_all(home);
1261 }
1262
1263 #[test]
1264 fn validate_read_existing_documents_as_structs_default_ten() {
1265 let name = random_string(None);
1266 let home = ".validate_read_existing_documents_as_structs_default_ten";
1267 let index_path = format!("{}/{}", home, name);
1268 let path = Path::new(&index_path);
1269 assert!(!path.exists());
1270
1271 let data = OldMan::default();
1272
1273 let mut builder = SurferBuilder::default();
1274 builder.set_home(home);
1275 builder.add_struct(name.clone(), &data);
1276
1277 let title = "The Old Man and the Sea".to_string();
1278 let body = "He was an old man who fished alone in a skiff in the Gulf Stream and he had gone eighty-four days now without taking a fish.".to_string();
1279 let old_man_doc = OldMan {
1280 title,
1281 body,
1282 };
1283
1284 let mut surfer = Surfer::new(builder.clone());
1285 for _ in 0..20 {
1286 let _ = surfer.insert_struct(&name, &old_man_doc).unwrap();
1287 }
1288
1289
1290 let query = "sea whale";
1291 let result = surfer.read_structs::<OldMan>(&name, query, None, None);
1292 assert!(result.is_ok());
1293 let result = result.unwrap().unwrap();
1294 assert_eq!(result.len(), 10);
1295
1296 let result = surfer.read_structs::<OldMan>(&name, query, Some(20), None);
1297 assert!(result.is_ok());
1298 let result = result.unwrap().unwrap();
1299 assert_eq!(result.len(), 20);
1300
1301 assert!(path.exists());
1302 let _ = remove_dir_all(index_path);
1303 let _ = remove_dir_all(home);
1304 }
1305
1306 #[derive(Serialize, Deserialize)]
1307 struct Dummy {
1308 x: String,
1309 y: String,
1310 z: u64,
1311 }
1312
1313 #[test]
1314 fn check_invalid_index_name() {
1315 let home = random_string(None);
1316 let data = Dummy {
1317 x: "X".to_owned(),
1318 y: "Y".to_owned(),
1319 z: 100u64,
1320 };
1321 let mut builder = SurferBuilder::default();
1322 builder.set_home(&home);
1323 builder.add_struct("dummy".to_string(), &data);
1324 let surfer = Surfer::try_from(builder).unwrap();
1325 let computed = surfer.which_index("crap");
1326 assert!(computed.is_none());
1327 let home = Path::new(&home);
1328 assert!(home.exists());
1329 let index_path = surfer.which_index("dummy").unwrap();
1330 let _ = remove_dir_all(&index_path);
1331 let _ = remove_dir_all(&home);
1332 }
1333
1334 #[test]
1335 fn check_invalid_index_insert() {
1336 let home = random_string(None);
1337 let data = Dummy {
1338 x: "X".to_owned(),
1339 y: "Y".to_owned(),
1340 z: 100u64,
1341 };
1342 let mut builder = SurferBuilder::default();
1343 builder.set_home(&home);
1344 builder.add_struct("dummy".to_string(), &data);
1345 let mut surfer = Surfer::try_from(builder).unwrap();
1346 let data = vec![data];
1347 let computed = surfer.insert_structs("crap", &data);
1348 assert!(computed.is_ok());
1349 let index_path = surfer.which_index("dummy").unwrap();
1350 let _ = remove_dir_all(&index_path);
1351 let _ = remove_dir_all(&home);
1352 }
1353
1354 #[test]
1355 fn check_invalid_index_lookup() {
1356 let name = random_string(None);
1357 let home = ".check_invalid_index_lookup";
1358 let index_path = format!("{}/{}", home, name);
1359 let path = Path::new(&index_path);
1360 assert!(!path.exists());
1361
1362
1363 let data = Dummy {
1364 x: "X".to_owned(),
1365 y: "Y".to_owned(),
1366 z: 100u64,
1367 };
1368 let mut builder = SurferBuilder::default();
1369 builder.set_home(&home);
1370 let mut surfer = Surfer::try_from(builder).unwrap();
1371 let _ = surfer.insert_struct("dummy", &data).unwrap();
1372 let computed = surfer.read_structs::<Dummy>("crap", "X", None, None);
1373 assert!(computed.is_ok());
1374 let computed = computed.unwrap();
1375 assert!(computed.is_none());
1376 let _ = remove_dir_all(&path);
1377 let _ = remove_dir_all(&home);
1378 }
1379
1380 #[test]
1381 fn validate_surfer_schema() {
1382 let data = Dummy {
1383 x: "X".to_owned(),
1384 y: "Y".to_owned(),
1385 z: 100u64,
1386 };
1387
1388 let data = utils::as_value(&data).unwrap();
1389 let (schema, mappings) = utils::to_schema(&data, None).unwrap();
1390 let surf_schema = SurferSchema::new(schema, mappings, false, false);
1391
1392 let mut computed1 = SurferBuilder::default();
1393 computed1.add_schema("dummy".to_string(), surf_schema.clone());
1394
1395 let mut computed2 = SurferBuilder::default();
1396 computed2.add_struct("dummy".to_string(), &data);
1397
1398 assert_eq!(computed1, computed2);
1399
1400 assert_eq!(format!("{:?}", computed1.schemas), format!("{:?}", computed2.schemas))
1401 }
1402
1403 #[derive(Serialize, Debug, Deserialize, PartialEq, PartialOrd, Clone)]
1405 struct UserInfo {
1406 first: String,
1407 last: String,
1408 age: u8,
1409 }
1410
1411 impl UserInfo {
1412 pub fn new(first: String, last: String, age: u8) -> Self {
1413 Self {
1414 first,
1415 last,
1416 age,
1417 }
1418 }
1419 }
1420
1421 impl Default for UserInfo {
1422 fn default() -> Self {
1423 let first = "".to_string();
1424 let last = "".to_string();
1425 let age = 0u8;
1426 UserInfo::new(first, last, age)
1427 }
1428 }
1429
1430 #[test]
1431 fn test_user_info() {
1432 let home = ".test_user_info".to_string();
1434 let index_name = "store".to_string();
1436
1437 let mut builder = SurferBuilder::default();
1439 builder.set_home(&home);
1440
1441 let data = UserInfo::default();
1442 builder.add_struct(index_name.clone(), &data);
1443
1444 let mut surfer = Surfer::try_from(builder).unwrap();
1446
1447 let first = "John".to_string();
1451 let last = "Doe".to_string();
1452 let age = 20u8;
1453 let john_doe = UserInfo::new(first, last, age);
1454
1455 let first = "Jane".to_string();
1457 let last = "Doe".to_string();
1458 let age = 18u8;
1459 let jane_doe = UserInfo::new(first, last, age);
1460
1461 let first = "Jonny".to_string();
1463 let last = "Doe".to_string();
1464 let age = 10u8;
1465 let jonny_doe = UserInfo::new(first, last, age);
1466
1467 let first = "Jinny".to_string();
1469 let last = "Doe".to_string();
1470 let age = 10u8;
1471 let jinny_doe = UserInfo::new(first, last, age);
1472
1473 let _ = surfer.insert_struct(&index_name, &john_doe).unwrap();
1477 let _ = surfer.insert_struct(&index_name, &jane_doe).unwrap();
1478
1479 let users = vec![jonny_doe.clone(), jinny_doe.clone()];
1481 let _ = surfer.insert_structs(&index_name, &users).unwrap();
1482
1483 block_thread(1);
1484
1485 let expected = vec![john_doe.clone()];
1489 let computed = surfer.read_all_structs::<UserInfo>(&index_name, "John").unwrap().unwrap();
1490 assert_eq!(expected, computed);
1491
1492 let mut expected = vec![john_doe.clone(), jane_doe.clone(), jonny_doe.clone(), jinny_doe.clone()];
1493 expected.sort();
1494 let mut computed = surfer.read_all_structs::<UserInfo>(&index_name, "doe").unwrap().unwrap();
1495 computed.sort();
1496 assert_eq!(expected, computed);
1497
1498 let mut expected = vec![jonny_doe.clone(), jinny_doe.clone()];
1500 expected.sort();
1501 let mut computed = surfer.read_all_structs_by_field::<UserInfo>(&index_name, "age", "10").unwrap().unwrap();
1502 computed.sort();
1503 assert_eq!(expected, computed);
1504
1505 let before = surfer.read_all_structs::<UserInfo>(&index_name, "doe").unwrap().unwrap();
1510 let before: HashSet<UserInfo> = HashSet::from_iter(before.into_iter());
1511
1512 surfer.delete_structs(&index_name, "john").unwrap();
1514
1515 let after = surfer.read_all_structs::<UserInfo>(&index_name, "doe").unwrap().unwrap();
1517 let after: HashSet<UserInfo> = HashSet::from_iter(after.into_iter());
1518 let computed: Vec<UserInfo> = before.difference(&after).map(|e| e.clone()).collect();
1520 let expected = vec![john_doe];
1522 assert_eq!(expected, computed);
1523
1524 let before = surfer.read_all_structs_by_field::<UserInfo>(&index_name, "age", "10").unwrap().unwrap();
1527 let before: HashSet<UserInfo> = HashSet::from_iter(before.into_iter());
1528
1529 surfer.delete_structs_by_field(&index_name, "age", "10").unwrap();
1531
1532 let after = surfer.read_all_structs_by_field::<UserInfo>(&index_name, "age", "10").unwrap().unwrap();
1534 let after: HashSet<UserInfo> = HashSet::from_iter(after.into_iter());
1535 let mut computed: Vec<UserInfo> = before.difference(&after).map(|e| e.clone()).collect();
1537 computed.sort();
1538 let mut expected = vec![jonny_doe, jinny_doe];
1540 expected.sort();
1541 assert_eq!(expected, computed);
1542
1543
1544 let path = surfer.which_index(&index_name).unwrap();
1546 let _ = remove_dir_all(&path);
1547 let _ = remove_dir_all(&home);
1548 }
1549
1550 #[test]
1551 fn test_where_clause() {
1552 let home = ".test_where_clause".to_string();
1554 let index_name = "store".to_string();
1556
1557 let mut builder = SurferBuilder::default();
1559 builder.set_home(&home);
1560
1561 let data = UserInfo::default();
1562 builder.add_struct(index_name.clone(), &data);
1563
1564 let surfer = Surfer::try_from(builder).unwrap();
1566 let mut surf = Surf::from(surfer);
1567 let surfer = &mut surf;
1568
1569 let first = "John".to_string();
1573 let last = "Doe".to_string();
1574 let age = 20u8;
1575 let john_doe = UserInfo::new(first, last, age);
1576
1577 let first = "Jane".to_string();
1579 let last = "Doe".to_string();
1580 let age = 18u8;
1581 let jane_doe = UserInfo::new(first, last, age);
1582
1583 let first = "Jonny".to_string();
1585 let last = "Doe".to_string();
1586 let age = 10u8;
1587 let jonny_doe = UserInfo::new(first, last, age);
1588
1589 let first = "Jinny".to_string();
1591 let last = "Doe".to_string();
1592 let age = 10u8;
1593 let jinny_doe = UserInfo::new(first, last, age);
1594
1595 let users = vec![john_doe.clone(), jane_doe.clone(), jonny_doe.clone(), jinny_doe.clone()];
1598 let _ = surfer.insert_structs(&index_name, &users).unwrap();
1599 block_thread(1);
1600
1601 let conditions = vec![OrCondition::from(("age".to_string(), "10".to_string()))];
1602 let mut expected = vec![jonny_doe.clone(), jinny_doe.clone()];
1603 let mut computed = surfer.select::<UserInfo>(&index_name, &conditions).unwrap().unwrap();
1604 expected.sort();
1605 computed.sort();
1606 assert_eq!(expected, computed);
1607
1608 let conditions = vec![OrCondition::from(("age".to_string(), "10".to_string())),
1609 OrCondition::from(("first".to_string(), "john".to_string()))];
1610 let mut expected = vec![john_doe.clone(), jonny_doe.clone(), jinny_doe.clone()];
1611 let mut computed = surfer.select::<UserInfo>(&index_name, &conditions).unwrap().unwrap();
1612 expected.sort();
1613 computed.sort();
1614 assert_eq!(expected, computed);
1615
1616
1617 let name_condition = AndCondition::new("first".to_string(), "jinny".to_string());
1618 let age_condition = AndCondition::new("age".to_string(), "10".to_string());
1619 let and_conditions = vec![name_condition, age_condition];
1620 let child_condition = OrCondition::new(and_conditions);
1621 let parent_condition = OrCondition::from(("first".to_string(), "john".to_string()));
1622 let conditions = vec![child_condition, parent_condition];
1623
1624 let mut expected = vec![john_doe.clone(), jinny_doe.clone()];
1625 let mut computed = surfer.select::<UserInfo>(&index_name, &conditions).unwrap().unwrap();
1626 expected.sort();
1627 computed.sort();
1628 assert_eq!(expected, computed);
1629
1630 let path = surfer.which_index(&index_name).unwrap();
1632 let _ = remove_dir_all(&path);
1633 let _ = remove_dir_all(&home);
1634 }
1635
1636 impl Ord for UserInfo {
1638 fn cmp(&self, other: &Self) -> Ordering {
1639 if self.first == other.first && self.last == other.last {
1640 return Ordering::Equal;
1641 };
1642 if self.first == other.first {
1643 if self.last > other.last {
1644 Ordering::Greater
1645 } else {
1646 Ordering::Less
1647 }
1648 } else {
1649 if self.first > other.first {
1650 Ordering::Greater
1651 } else {
1652 Ordering::Less
1653 }
1654 }
1655 }
1656 }
1657
1658 impl Eq for UserInfo {}
1660
1661 impl Hash for UserInfo {
1663 fn hash<H: Hasher>(&self, state: &mut H) {
1664 for i in self.first.as_bytes() {
1665 state.write_u8(*i);
1666 }
1667 for i in self.last.as_bytes() {
1668 state.write_u8(*i);
1669 }
1670 state.write_u8(self.age);
1671 state.finish();
1672 }
1673 }
1674}