use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;
use khive_types::SubstrateKind;
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum TextGatherMode {
#[default]
Ranked,
Unranked,
RankWithinCap,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct TextSearchOptions {
pub gather_mode: TextGatherMode,
pub gather_limit: Option<u32>,
}
impl Default for TextSearchOptions {
fn default() -> Self {
Self {
gather_mode: TextGatherMode::Ranked,
gather_limit: None,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TextTermStatsRequest {
pub terms: Vec<String>,
pub filter: Option<TextFilter>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TextTermStats {
pub term: String,
pub sanitized_term: String,
pub document_frequency: u64,
pub document_count: u64,
pub inverse_document_frequency: f64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TextDocument {
pub subject_id: Uuid,
pub kind: SubstrateKind,
pub namespace: String,
pub title: Option<String>,
pub body: String,
pub tags: Vec<String>,
pub metadata: Option<Value>,
pub updated_at: DateTime<Utc>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct TextFilter {
pub ids: Vec<Uuid>,
pub kinds: Vec<SubstrateKind>,
pub namespaces: Vec<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum TextQueryMode {
Plain,
Phrase,
AnyTerm,
}
#[derive(Deserialize)]
struct TextSearchRequestRaw {
query: String,
mode: TextQueryMode,
filter: Option<TextFilter>,
top_k: u32,
snippet_chars: usize,
}
impl TryFrom<TextSearchRequestRaw> for TextSearchRequest {
type Error = String;
fn try_from(raw: TextSearchRequestRaw) -> Result<Self, Self::Error> {
if raw.top_k == 0 {
return Err("TextSearchRequest: top_k must be > 0".into());
}
Ok(Self {
query: raw.query,
mode: raw.mode,
filter: raw.filter,
top_k: raw.top_k,
snippet_chars: raw.snippet_chars,
})
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(try_from = "TextSearchRequestRaw")]
pub struct TextSearchRequest {
pub query: String,
pub mode: TextQueryMode,
pub filter: Option<TextFilter>,
pub top_k: u32,
pub snippet_chars: usize,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TextSearchHit {
pub subject_id: Uuid,
pub score: khive_score::DeterministicScore,
pub rank: u32,
pub title: Option<String>,
pub snippet: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TextIndexStats {
pub document_count: u64,
pub needs_rebuild: bool,
pub last_rebuild_at: Option<DateTime<Utc>>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum IndexRebuildScope {
Full,
Entities(Vec<Uuid>),
}