use std::collections::HashMap;
use std::sync::Arc;
use crate::error::Result;
use crate::lexical::query::{LexicalSearchResults, Query};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum SortOrder {
#[default]
Asc,
Desc,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum SortField {
#[default]
Score,
Field {
name: String,
order: SortOrder,
},
}
#[derive(Debug, Clone)]
pub struct LexicalSearchParams {
pub limit: usize,
pub min_score: f32,
pub load_documents: bool,
pub timeout_ms: Option<u64>,
pub parallel: bool,
pub sort_by: SortField,
}
impl Default for LexicalSearchParams {
fn default() -> Self {
LexicalSearchParams {
limit: 10,
min_score: 0.0,
load_documents: true,
timeout_ms: None,
parallel: false,
sort_by: SortField::default(),
}
}
}
#[derive(Debug)]
pub enum LexicalSearchQuery {
Dsl(String),
Obj(Box<dyn Query>),
}
#[derive(Debug)]
pub struct LexicalSearchRequest {
pub query: LexicalSearchQuery,
pub params: LexicalSearchParams,
pub field_boosts: HashMap<String, f32>,
}
impl Clone for LexicalSearchQuery {
fn clone(&self) -> Self {
match self {
LexicalSearchQuery::Dsl(s) => LexicalSearchQuery::Dsl(s.clone()),
LexicalSearchQuery::Obj(q) => LexicalSearchQuery::Obj(q.clone_box()),
}
}
}
impl Clone for LexicalSearchRequest {
fn clone(&self) -> Self {
LexicalSearchRequest {
query: self.query.clone(),
params: self.params.clone(),
field_boosts: self.field_boosts.clone(),
}
}
}
impl From<String> for LexicalSearchQuery {
fn from(s: String) -> Self {
LexicalSearchQuery::Dsl(s)
}
}
impl From<&str> for LexicalSearchQuery {
fn from(s: &str) -> Self {
LexicalSearchQuery::Dsl(s.to_string())
}
}
impl From<Box<dyn Query>> for LexicalSearchQuery {
fn from(q: Box<dyn Query>) -> Self {
LexicalSearchQuery::Obj(q)
}
}
impl LexicalSearchQuery {
pub fn into_query(
self,
analyzer: &Arc<dyn crate::analysis::analyzer::analyzer::Analyzer>,
) -> crate::error::Result<Box<dyn Query>> {
match self {
LexicalSearchQuery::Dsl(dsl_string) => {
let parser =
crate::lexical::query::parser::LexicalQueryParser::new(analyzer.clone());
parser.parse(&dsl_string)
}
LexicalSearchQuery::Obj(query) => Ok(query),
}
}
pub fn unwrap_query(self) -> crate::error::Result<Box<dyn Query>> {
match self {
LexicalSearchQuery::Obj(query) => Ok(query),
LexicalSearchQuery::Dsl(_) => Err(crate::error::LaurusError::invalid_argument(
"Expected Query object, found DSL string",
)),
}
}
}
impl LexicalSearchRequest {
pub fn new(query: Box<dyn Query>) -> Self {
LexicalSearchRequest {
query: LexicalSearchQuery::Obj(query),
params: LexicalSearchParams::default(),
field_boosts: HashMap::new(),
}
}
pub fn from_dsl(dsl: impl Into<String>) -> Self {
LexicalSearchRequest {
query: LexicalSearchQuery::Dsl(dsl.into()),
params: LexicalSearchParams::default(),
field_boosts: HashMap::new(),
}
}
pub fn limit(mut self, limit: usize) -> Self {
self.params.limit = limit;
self
}
pub fn min_score(mut self, min_score: f32) -> Self {
self.params.min_score = min_score;
self
}
pub fn load_documents(mut self, load_documents: bool) -> Self {
self.params.load_documents = load_documents;
self
}
pub fn timeout_ms(mut self, timeout_ms: u64) -> Self {
self.params.timeout_ms = Some(timeout_ms);
self
}
pub fn parallel(mut self, parallel: bool) -> Self {
self.params.parallel = parallel;
self
}
pub fn sort_by_field_asc(mut self, field: &str) -> Self {
self.params.sort_by = SortField::Field {
name: field.to_string(),
order: SortOrder::Asc,
};
self
}
pub fn sort_by_field_desc(mut self, field: &str) -> Self {
self.params.sort_by = SortField::Field {
name: field.to_string(),
order: SortOrder::Desc,
};
self
}
pub fn sort_by_score(mut self) -> Self {
self.params.sort_by = SortField::Score;
self
}
pub fn with_field_boost(mut self, field: impl Into<String>, boost: f32) -> Self {
self.field_boosts.insert(field.into(), boost);
self
}
}
pub trait LexicalSearcher: Send + Sync + std::fmt::Debug {
fn search(&self, request: LexicalSearchRequest) -> Result<LexicalSearchResults>;
fn count(&self, request: LexicalSearchRequest) -> Result<u64>;
}