Skip to main content

linkrs_wire/
fulltext.rs

1//! Fulltext protocol DTOs.
2//!
3//! Transport-independent request/response shapes for fulltext index management
4//! and search, shared between the server handlers and CLI clients.
5//!
6//! These types provide structured typing for fulltext-specific operations,
7//! mirroring the vector wire DTOs for consistency.
8
9use serde::{Deserialize, Serialize};
10
11/// Fulltext search request.
12#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
13pub struct FulltextSearchRequest {
14    /// Index name to search
15    pub index_name: String,
16    /// Search query string
17    pub query: String,
18    /// Maximum number of results to return
19    #[serde(default)]
20    pub limit: Option<usize>,
21    /// Offset for pagination
22    #[serde(default)]
23    pub offset: Option<usize>,
24}
25
26/// Fulltext search response.
27#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
28pub struct FulltextSearchResponse {
29    /// Search results
30    pub results: Vec<FulltextSearchResult>,
31    /// Total number of matching documents
32    pub total_hits: usize,
33    /// Search execution time in milliseconds
34    pub took_ms: u64,
35}
36
37/// One scored hit of a [`FulltextSearchResponse`].
38#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
39pub struct FulltextSearchResult {
40    /// Document ID
41    pub doc_id: String,
42    /// BM25 relevance score
43    pub score: f32,
44    /// Optional highlight information for matched fields
45    #[serde(default)]
46    pub highlights: Option<Vec<HighlightResult>>,
47}
48
49/// Highlight information for a matched field.
50#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
51pub struct HighlightResult {
52    /// Field name that matched
53    pub field: String,
54    /// Highlighted text fragments
55    pub fragments: Vec<String>,
56}
57
58/// Create a fulltext index request.
59#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
60pub struct CreateFulltextIndexRequest {
61    /// Index name
62    pub index_name: String,
63    /// Schema (tag) name
64    pub schema_name: String,
65    /// Fields to index
66    pub fields: Vec<FulltextFieldDef>,
67    /// Whether to skip creation if index already exists
68    #[serde(default)]
69    pub if_not_exists: Option<bool>,
70}
71
72/// Fulltext field definition for index creation.
73#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
74pub struct FulltextFieldDef {
75    /// Field name
76    pub field_name: String,
77    /// Analyzer to use (e.g., "standard", "jieba", "raw")
78    #[serde(default)]
79    pub analyzer: Option<String>,
80    /// Field boost factor for scoring
81    #[serde(default)]
82    pub boost: Option<f32>,
83}
84
85/// Drop fulltext index request.
86#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
87pub struct DropFulltextIndexRequest {
88    /// Index name to drop
89    pub index_name: String,
90    /// Whether to skip error if index doesn't exist
91    #[serde(default)]
92    pub if_exists: Option<bool>,
93}
94
95/// Fulltext index information.
96#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
97pub struct FulltextIndexInfo {
98    /// Index name
99    pub index_name: String,
100    /// Space (namespace) ID
101    pub space_id: u64,
102    /// Tag (vertex type) name
103    pub tag_name: String,
104    /// Field name
105    pub field_name: String,
106    /// Index status
107    pub status: String,
108    /// Number of documents indexed
109    pub doc_count: u64,
110}
111
112/// List fulltext indexes response.
113#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
114pub struct ListFulltextIndexesResponse {
115    /// All fulltext indexes
116    pub indexes: Vec<FulltextIndexInfo>,
117}
118
119/// Rebuild a fulltext index request.
120///
121/// The rebuild runs asynchronously: the handler returns a rebuild id
122/// immediately and the caller polls the rebuild status endpoint.
123#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
124pub struct RebuildFulltextIndexRequest {
125    /// Space (namespace) ID
126    pub space_id: u64,
127    /// Tag (vertex type) name
128    pub tag_name: String,
129    /// Field name
130    pub field_name: String,
131}
132
133/// Rebuild a fulltext index response (accepted async task).
134#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
135pub struct RebuildFulltextIndexResponse {
136    /// Async rebuild task id for status polling
137    pub rebuild_id: String,
138    /// Initial task status (`running`)
139    pub status: String,
140    /// Space (namespace) ID
141    pub space_id: u64,
142    /// Tag (vertex type) name
143    pub tag_name: String,
144    /// Field name
145    pub field_name: String,
146}
147
148/// Fulltext rebuild task status.
149#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
150pub struct FulltextRebuildStatusResponse {
151    /// Async rebuild task id
152    pub rebuild_id: String,
153    /// Task status (`running`, `completed`, `failed`)
154    pub status: String,
155    /// Current rebuild phase, if known
156    #[serde(default)]
157    pub phase: Option<String>,
158    /// Outbox generation used by this rebuild attempt, if known
159    #[serde(default)]
160    pub generation: Option<u64>,
161    /// Documents scanned from primary storage
162    #[serde(default)]
163    pub docs_scanned: u64,
164    /// Documents applied (backfill + replay)
165    #[serde(default)]
166    pub docs_applied: u64,
167    /// Documents skipped as unrepresentable
168    #[serde(default)]
169    pub docs_skipped: u64,
170    /// Failure reason, if failed
171    #[serde(default)]
172    pub error: Option<String>,
173}
174
175/// Clear a fulltext index request.
176///
177/// Explicit destructive operation: drops all indexed documents without
178/// backfill. Requires `force = true`.
179#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
180pub struct ClearFulltextIndexRequest {
181    /// Space (namespace) ID
182    pub space_id: u64,
183    /// Tag (vertex type) name
184    pub tag_name: String,
185    /// Field name
186    pub field_name: String,
187    /// Explicit confirmation of the destructive clear
188    pub force: bool,
189}
190
191/// Clear a fulltext index response.
192#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
193pub struct ClearFulltextIndexResponse {
194    /// Always true on success
195    pub ok: bool,
196    /// Space (namespace) ID
197    pub space_id: u64,
198    /// Tag (vertex type) name
199    pub tag_name: String,
200    /// Field name
201    pub field_name: String,
202}