use crate::order::{OrderClause, OrderTarget};
use crate::values::{FilterValue, IntoSqlValue};
use crate::{NullOrder, SortDirection};
use super::expr::FilterExpr;
use super::op::FilterOp;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VectorMetric {
L2,
Cosine,
InnerProduct,
}
impl VectorMetric {
pub const fn sql_operator(self) -> &'static str {
match self {
Self::L2 => "<->",
Self::Cosine => "<=>",
Self::InnerProduct => "<#>",
}
}
pub fn from_opclass(opclass: &str) -> Option<Self> {
match opclass {
"vector_l2_ops" => Some(Self::L2),
"vector_cosine_ops" => Some(Self::Cosine),
"vector_ip_ops" => Some(Self::InnerProduct),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct VectorDistanceFilter {
pub column: &'static str,
pub metric: VectorMetric,
pub query_vector: Vec<f32>,
pub op: FilterOp,
pub value: FilterValue,
}
#[derive(Debug, Clone)]
pub struct VectorDistanceExpr {
column: &'static str,
metric: VectorMetric,
query_vector: Vec<f32>,
}
impl VectorDistanceExpr {
pub(super) fn new(column: &'static str, metric: VectorMetric, query_vector: Vec<f32>) -> Self {
Self {
column,
metric,
query_vector,
}
}
fn into_filter<V: IntoSqlValue>(self, op: FilterOp, value: V) -> FilterExpr {
FilterExpr::VectorDistance(VectorDistanceFilter {
column: self.column,
metric: self.metric,
query_vector: self.query_vector,
op,
value: FilterValue::Single(value.into_sql_value()),
})
}
pub fn lt<V: IntoSqlValue>(self, value: V) -> FilterExpr {
self.into_filter(FilterOp::Lt, value)
}
pub fn lte<V: IntoSqlValue>(self, value: V) -> FilterExpr {
self.into_filter(FilterOp::Lte, value)
}
pub fn gt<V: IntoSqlValue>(self, value: V) -> FilterExpr {
self.into_filter(FilterOp::Gt, value)
}
pub fn gte<V: IntoSqlValue>(self, value: V) -> FilterExpr {
self.into_filter(FilterOp::Gte, value)
}
pub fn eq<V: IntoSqlValue>(self, value: V) -> FilterExpr {
self.into_filter(FilterOp::Eq, value)
}
pub fn asc(self) -> OrderClause {
self.order(SortDirection::Asc)
}
pub fn desc(self) -> OrderClause {
self.order(SortDirection::Desc)
}
fn order(self, direction: SortDirection) -> OrderClause {
OrderClause {
target: OrderTarget::VectorDistance {
column: self.column,
metric: self.metric,
query_vector: self.query_vector,
},
direction,
null_order: NullOrder::Last,
}
}
}
#[cfg(test)]
mod tests;