flusso_query/handles/object.rs
1//! Sub-document and opaque field handles: the flattened [`Object`], and the
2//! non-searchable [`Binary`] / [`Json`] fields (existence, or a raw clause).
3
4use std::marker::PhantomData;
5
6use serde_json::Value;
7
8use super::exists_q;
9use crate::query::{Query, Root};
10
11// ---- Object ----------------------------------------------------------------
12
13/// An `object` sub-document — a `group` or a to-one (`belongs_to`/`has_one`) join. Objects are
14/// **flattened**, so their sub-fields are queried by their own scope-`S`
15/// dotted-path handles directly (`Account::tier()`); this handle is for the
16/// object itself. `S` is the enclosing scope (`Root` at the top level).
17#[derive(Debug, Clone)]
18pub struct Object<S = Root> {
19 path: String,
20 _scope: PhantomData<fn() -> S>,
21}
22
23impl<S> Object<S> {
24 /// Build a handle for the object at `path`.
25 pub fn at(path: impl Into<String>) -> Self {
26 Self {
27 path: path.into(),
28 _scope: PhantomData,
29 }
30 }
31
32 /// The object is present — most useful on a nullable to-one join.
33 pub fn exists(&self) -> Query<S> {
34 exists_q(&self.path)
35 }
36}
37
38// ---- Binary ----------------------------------------------------------------
39
40/// A `binary` field — base64-encoded, not searchable. Only existence.
41#[derive(Debug, Clone)]
42pub struct Binary<S = Root> {
43 path: String,
44 _scope: PhantomData<fn() -> S>,
45}
46
47impl<S> Binary<S> {
48 /// Build a handle for the field at `path`.
49 pub fn at(path: impl Into<String>) -> Self {
50 Self {
51 path: path.into(),
52 _scope: PhantomData,
53 }
54 }
55
56 /// The field has a non-null value.
57 pub fn exists(&self) -> Query<S> {
58 exists_q(&self.path)
59 }
60}
61
62// ---- Json ------------------------------------------------------------------
63
64/// An untyped `object`/`json` field. The escape hatch: existence, or a raw
65/// clause spliced in verbatim.
66#[derive(Debug, Clone)]
67pub struct Json<S = Root> {
68 path: String,
69 _scope: PhantomData<fn() -> S>,
70}
71
72impl<S> Json<S> {
73 /// Build a handle for the field at `path`.
74 pub fn at(path: impl Into<String>) -> Self {
75 Self {
76 path: path.into(),
77 _scope: PhantomData,
78 }
79 }
80
81 /// The field has a non-null value.
82 pub fn exists(&self) -> Query<S> {
83 exists_q(&self.path)
84 }
85
86 /// Splice a raw OpenSearch query clause in verbatim.
87 pub fn raw(&self, clause: Value) -> Query<S> {
88 Query::leaf(clause)
89 }
90}