use tantivy::{
Index,
schema::{
DateOptions, FAST, Field, STORED, STRING, Schema, SchemaBuilder, TextFieldIndexing,
TextOptions,
},
tokenizer::{LowerCaser, SimpleTokenizer, TextAnalyzer},
};
#[derive(Debug, Clone)]
pub struct SearchFields {
pub title: Field,
pub body: Field,
pub url: Field,
pub lang: Field,
pub tags: Field,
pub date: Field,
}
pub fn create_search_schema() -> (Schema, SearchFields) {
let mut builder = SchemaBuilder::new();
let title_options = TextOptions::default()
.set_indexing_options(
TextFieldIndexing::default()
.set_tokenizer("default")
.set_index_option(tantivy::schema::IndexRecordOption::WithFreqsAndPositions),
)
.set_stored();
let title = builder.add_text_field("title", title_options);
let body_options = TextOptions::default().set_indexing_options(
TextFieldIndexing::default()
.set_tokenizer("default")
.set_index_option(tantivy::schema::IndexRecordOption::WithFreqsAndPositions),
);
let body = builder.add_text_field("body", body_options);
let url = builder.add_text_field("url", STRING | STORED);
let lang = builder.add_text_field("lang", STRING | STORED | FAST);
let tags_options = TextOptions::default()
.set_indexing_options(
TextFieldIndexing::default()
.set_tokenizer("default")
.set_index_option(tantivy::schema::IndexRecordOption::WithFreqs),
)
.set_stored();
let tags = builder.add_text_field("tags", tags_options);
let date_options = DateOptions::default().set_stored().set_fast();
let date = builder.add_date_field("date", date_options);
let schema = builder.build();
let fields = SearchFields {
title,
body,
url,
lang,
tags,
date,
};
(schema, fields)
}
pub fn register_tokenizers(index: &Index) {
let tokenizer = TextAnalyzer::builder(SimpleTokenizer::default())
.filter(LowerCaser)
.build();
index.tokenizers().register("default", tokenizer);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_schema() {
let (schema, fields) = create_search_schema();
assert!(schema.get_field("title").is_ok());
assert!(schema.get_field("body").is_ok());
assert!(schema.get_field("url").is_ok());
assert!(schema.get_field("lang").is_ok());
assert!(schema.get_field("tags").is_ok());
assert!(schema.get_field("date").is_ok());
assert_eq!(fields.title, schema.get_field("title").unwrap());
assert_eq!(fields.body, schema.get_field("body").unwrap());
assert_eq!(fields.url, schema.get_field("url").unwrap());
}
#[test]
fn test_title_field_is_stored() {
let (schema, fields) = create_search_schema();
let field_entry = schema.get_field_entry(fields.title);
assert!(field_entry.is_indexed());
assert_eq!(field_entry.name(), "title");
}
#[test]
fn test_url_field_is_string() {
let (schema, fields) = create_search_schema();
let field_entry = schema.get_field_entry(fields.url);
assert!(field_entry.is_indexed());
assert_eq!(field_entry.name(), "url");
}
#[test]
fn test_register_tokenizers() {
let (schema, _) = create_search_schema();
let index = Index::create_in_ram(schema);
register_tokenizers(&index);
let tokenizer = index.tokenizers().get("default");
assert!(tokenizer.is_some());
}
}