use serde_json::{Map, Value};
use crate::query::Query;
mod compound;
mod extra;
mod geo;
mod map;
mod nested;
mod object;
mod scalar;
mod sort;
mod string;
pub use compound::{
BoostingQuery, ConstantScoreQuery, DisMaxQuery, FunctionScoreQuery, boosting, constant_score,
dis_max, function_score,
};
pub use extra::{
CombinedFieldsQuery, DistanceFeatureQuery, IdsQuery, MoreLikeThisQuery, QueryStringQuery,
RankFeatureQuery, ScriptQuery, ScriptScoreQuery, SimpleQueryStringQuery, combined_fields,
distance_feature, ids, more_like_this, query_string, rank_feature, script, script_score,
simple_query_string,
};
pub use geo::{Geo, GeoDistanceQuery, GeoPoint};
pub use map::{DateMap, KeywordMap, MapSearch, NumberMap, TextMap};
pub use nested::{Nested, NestedProjection, NestedQuery};
pub use object::{Binary, Json, Object};
pub use scalar::{Bool, Date, EqQuery, Number, RangeQuery, TermsQuery};
pub use sort::{Sort, SortMode, SortOrder};
pub use string::{
FuzzyQuery, Keyword, MatchQuery, MultiMatchQuery, PrefixQuery, RegexpQuery, TermQuery, Text,
WildcardQuery, multi_match,
};
fn single<S>(wrapper: &str, path: &str, value: Value) -> Query<S> {
let mut inner = Map::new();
inner.insert(path.to_string(), value);
wrap(wrapper, inner)
}
fn wrap<S>(wrapper: &str, body: Map<String, Value>) -> Query<S> {
let mut outer = Map::new();
outer.insert(wrapper.to_string(), Value::Object(body));
Query::leaf(Value::Object(outer))
}
#[derive(Debug, Clone, Default)]
pub(crate) struct Common {
boost: Option<f32>,
name: Option<String>,
}
impl Common {
pub(crate) fn set_boost(&mut self, boost: f32) {
self.boost = Some(boost);
}
pub(crate) fn set_name(&mut self, name: String) {
self.name = Some(name);
}
pub(crate) fn is_empty(&self) -> bool {
self.boost.is_none() && self.name.is_none()
}
pub(crate) fn write(&self, map: &mut Map<String, Value>) {
if let Some(boost) = self.boost {
map.insert("boost".to_string(), Value::from(boost));
}
if let Some(name) = &self.name {
map.insert("_name".to_string(), Value::String(name.clone()));
}
}
}
macro_rules! common_opts {
($field:ident) => {
#[must_use]
pub fn boost(mut self, boost: f32) -> Self {
self.$field.set_boost(boost);
self
}
#[must_use]
pub fn name(mut self, name: impl Into<String>) -> Self {
self.$field.set_name(name.into());
self
}
};
}
pub(crate) use common_opts;
fn keyed_value_query<S>(
wrapper: &str,
path: &str,
key: &str,
value: Value,
mut opts: Map<String, Value>,
) -> Query<S> {
if opts.is_empty() {
single(wrapper, path, value)
} else {
opts.insert(key.to_string(), value);
single(wrapper, path, Value::Object(opts))
}
}
fn exists_q<S>(path: &str) -> Query<S> {
let mut inner = Map::new();
inner.insert("field".to_string(), Value::String(path.to_string()));
let mut outer = Map::new();
outer.insert("exists".to_string(), Value::Object(inner));
Query::leaf(Value::Object(outer))
}
pub(crate) fn match_all_value() -> Value {
let mut outer = Map::new();
outer.insert("match_all".to_string(), Value::Object(Map::new()));
Value::Object(outer)
}
pub mod kind {
#[derive(Debug)]
pub enum Keyword {}
#[derive(Debug)]
pub enum Text {}
#[derive(Debug)]
pub enum Number {}
#[derive(Debug)]
pub enum Date {}
}
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a valid value for a `{K}` field",
label = "unsupported field type",
note = "use a built-in leaf type, or add `#[derive(FlussoValue)]` (with the matching kind) to `{Self}`"
)]
pub trait FlussoValue<K> {}
impl FlussoValue<kind::Keyword> for String {}
impl FlussoValue<kind::Keyword> for &str {}
#[cfg(feature = "uuid")]
impl FlussoValue<kind::Keyword> for uuid::Uuid {}
#[cfg(feature = "uuid")]
impl FlussoValue<kind::Keyword> for &uuid::Uuid {}
impl FlussoValue<kind::Text> for String {}
impl FlussoValue<kind::Text> for &str {}
impl FlussoValue<kind::Number> for i8 {}
impl FlussoValue<kind::Number> for i16 {}
impl FlussoValue<kind::Number> for i32 {}
impl FlussoValue<kind::Number> for i64 {}
impl FlussoValue<kind::Number> for f32 {}
impl FlussoValue<kind::Number> for f64 {}
#[cfg(feature = "decimal")]
impl FlussoValue<kind::Number> for crate::Decimal {}
impl FlussoValue<kind::Date> for String {}
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a valid map for a `{K}` field",
label = "unsupported map type",
note = "use `HashMap<String, V>` with a `{K}` value type, or add `#[derive(FlussoMap)]` (with the matching kind) to `{Self}`"
)]
pub trait FlussoMap<K> {}
impl<K, V: FlussoValue<K>> FlussoMap<K> for std::collections::HashMap<String, V> {}