qql_core/ast/statement/retrieval.rs
1//! Typed AST for retrieval statements (SCROLL, COUNT, FACET).
2
3use super::query::QueryCollection;
4use super::types::*;
5use crate::ast::{FilterExpr, Value};
6use alloc::string::String;
7
8/// `ORDER BY` tail of a `SCROLL` statement (OpenAPI `ScrollRequest.order_by`).
9#[derive(Debug, Clone, PartialEq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct ScrollOrderBy {
12 /// Payload field to sort on.
13 pub field: String,
14 /// Sort direction (`ASC` default).
15 pub direction: OrderDirection,
16 /// Optional paging origin: resume ordering from this payload value
17 /// (OpenAPI `OrderBy.start_from`: integer, float, or datetime string).
18 pub start_from: Option<Value>,
19}
20
21/// `SCROLL FROM <collection> … LIMIT n` — cursor-based point iteration.
22#[derive(Debug, Clone, PartialEq)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct ScrollStmt {
25 /// Collection to scroll.
26 pub collection: String,
27 /// Maximum number of points per page.
28 pub limit: u64,
29 /// Optional `WHERE` filter.
30 pub filter: Option<Box<FilterExpr>>,
31 /// `AFTER` cursor — resume scrolling after this point ID.
32 pub after: Option<PointId>,
33 /// Optional `ORDER BY` payload ordering (OpenAPI `order_by`).
34 pub order_by: Option<ScrollOrderBy>,
35 /// `SHARD '<key>'` routing key.
36 pub shard_key: Option<super::ShardKey>,
37 /// Optional `WITH PAYLOAD` selector. Defaults to all payload when `None`.
38 pub with_payload: Option<PayloadSelector>,
39 /// Optional `WITH VECTOR` selector. Defaults to no vectors when `None`.
40 pub with_vector: Option<VectorSelector>,
41 /// Optional limit parameter placeholder (`:limit` or `?`).
42 #[cfg_attr(
43 feature = "serde",
44 serde(default, skip_serializing_if = "Option::is_none")
45 )]
46 pub limit_param: Option<String>,
47 /// Source span of the limit parameter placeholder, if unbound.
48 #[cfg_attr(
49 feature = "serde",
50 serde(default, skip_serializing_if = "Option::is_none")
51 )]
52 pub limit_span: Option<crate::error::Span>,
53}
54
55/// `COUNT FROM <collection> [WHERE …]` statement.
56#[derive(Debug, Clone, PartialEq)]
57#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58pub struct CountStmt {
59 /// Collection to count (explicit or inherited).
60 pub collection: QueryCollection,
61 /// Optional `WHERE` filter.
62 pub filter: Option<Box<FilterExpr>>,
63 /// `SHARD '<key>'` routing key.
64 pub shard_key: Option<super::ShardKey>,
65 /// `WITH (exact = …)` — require exact counts.
66 pub exact: Option<bool>,
67}
68
69/// In-database categorical facet aggregation statement (`FACET <key> FROM <collection>`).
70///
71/// Compiles to Qdrant's `/collections/{collection}/facet` endpoint (REST) or `Points.Facet` (gRPC), returning hit counts
72/// per unique value for a payload field without retrieving full point records.
73///
74/// # Supported clauses
75/// - `WHERE`: Optional filter restricting candidate points.
76/// - `LIMIT`: Maximum number of distinct facet values to return.
77/// - `EXACT`: Whether to compute exact distributed counts across shards.
78/// - `SHARD`: Target shard key for tenant-partitioned collections.
79#[derive(Debug, Clone, PartialEq)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
81pub struct FacetStmt {
82 /// Payload field name to aggregate values for.
83 pub key: String,
84 /// Target collection.
85 pub collection: QueryCollection,
86 /// Optional point filter scoping the aggregation.
87 pub filter: Option<Box<FilterExpr>>,
88 /// Maximum number of unique facet hits to return.
89 pub limit: Option<u64>,
90 /// Whether to compute exact distributed counts across shards.
91 pub exact: Option<bool>,
92 /// Optional shard key partition routing.
93 pub shard_key: Option<super::ShardKey>,
94 /// Optional limit parameter placeholder (`:limit` or `?`).
95 #[cfg_attr(
96 feature = "serde",
97 serde(default, skip_serializing_if = "Option::is_none")
98 )]
99 pub limit_param: Option<String>,
100 /// Source span of the limit parameter placeholder, if unbound.
101 #[cfg_attr(
102 feature = "serde",
103 serde(default, skip_serializing_if = "Option::is_none")
104 )]
105 pub limit_span: Option<crate::error::Span>,
106}