use serde_json::{Map, Value};
use crate::query::AsQuery;
#[derive(Debug, Clone, Copy)]
pub enum SortOrder {
Asc,
Desc,
}
impl SortOrder {
pub(crate) fn as_str(self) -> &'static str {
match self {
SortOrder::Asc => "asc",
SortOrder::Desc => "desc",
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum SortMode {
Min,
Max,
Avg,
Sum,
Median,
}
impl SortMode {
fn as_str(self) -> &'static str {
match self {
SortMode::Min => "min",
SortMode::Max => "max",
SortMode::Avg => "avg",
SortMode::Sum => "sum",
SortMode::Median => "median",
}
}
}
#[derive(Debug, Clone)]
pub struct Sort {
key: String,
body: Map<String, Value>,
}
impl Sort {
pub(crate) fn new(field: &str, order: SortOrder) -> Self {
let mut body = Map::new();
body.insert(
"order".to_string(),
Value::String(order.as_str().to_string()),
);
Self {
key: field.to_string(),
body,
}
}
#[must_use]
pub fn score() -> Self {
let mut sort = Self {
key: "_score".to_string(),
body: Map::new(),
};
sort.body
.insert("order".to_string(), Value::String("desc".to_string()));
sort
}
#[must_use]
pub fn script(
script_type: impl Into<String>,
source: impl Into<String>,
order: SortOrder,
) -> Self {
let mut script = Map::new();
script.insert("source".to_string(), Value::String(source.into()));
let mut body = Map::new();
body.insert("type".to_string(), Value::String(script_type.into()));
body.insert("script".to_string(), Value::Object(script));
body.insert(
"order".to_string(),
Value::String(order.as_str().to_string()),
);
Self {
key: "_script".to_string(),
body,
}
}
pub(crate) fn from_parts(key: String, body: Map<String, Value>) -> Self {
Self { key, body }
}
#[must_use]
pub fn asc(mut self) -> Self {
self.body
.insert("order".to_string(), Value::String("asc".to_string()));
self
}
#[must_use]
pub fn desc(mut self) -> Self {
self.body
.insert("order".to_string(), Value::String("desc".to_string()));
self
}
#[must_use]
pub fn missing_first(mut self) -> Self {
self.body
.insert("missing".to_string(), Value::String("_first".to_string()));
self
}
#[must_use]
pub fn missing_last(mut self) -> Self {
self.body
.insert("missing".to_string(), Value::String("_last".to_string()));
self
}
#[must_use]
pub fn missing(mut self, value: impl Into<Value>) -> Self {
self.body.insert("missing".to_string(), value.into());
self
}
#[must_use]
pub fn mode(mut self, mode: SortMode) -> Self {
self.body
.insert("mode".to_string(), Value::String(mode.as_str().to_string()));
self
}
#[must_use]
pub fn unmapped_type(mut self, unmapped_type: impl Into<String>) -> Self {
self.body.insert(
"unmapped_type".to_string(),
Value::String(unmapped_type.into()),
);
self
}
#[must_use]
pub fn numeric_type(mut self, numeric_type: impl Into<String>) -> Self {
self.body.insert(
"numeric_type".to_string(),
Value::String(numeric_type.into()),
);
self
}
#[must_use]
pub fn format(mut self, format: impl Into<String>) -> Self {
self.body
.insert("format".to_string(), Value::String(format.into()));
self
}
#[must_use]
pub fn nested(mut self, path: impl Into<String>) -> Self {
let mut nested = Map::new();
nested.insert("path".to_string(), Value::String(path.into()));
self.body
.insert("nested".to_string(), Value::Object(nested));
self
}
#[must_use]
pub fn nested_filtered<S>(mut self, path: impl Into<String>, filter: impl AsQuery<S>) -> Self {
let mut nested = Map::new();
nested.insert("path".to_string(), Value::String(path.into()));
if let Some(query) = filter.into_query() {
nested.insert("filter".to_string(), query.to_value());
}
self.body
.insert("nested".to_string(), Value::Object(nested));
self
}
pub(crate) fn to_value(&self) -> Value {
let mut outer = Map::new();
outer.insert(self.key.clone(), Value::Object(self.body.clone()));
Value::Object(outer)
}
}