sonic_channel/commands/
query.rs

1use super::StreamCommand;
2use crate::misc::Dest;
3use crate::protocol;
4use crate::result::*;
5
6/// Parameters for the `query` command
7#[derive(Debug, Clone)]
8pub struct QueryRequest {
9    /// Collection and bucket where we should search for objects.
10    pub dest: Dest,
11    /// Searchable terms.
12    pub terms: String,
13    /// Language of the search data. If None, the client will try to determine based on the `terms`.
14    pub lang: Option<whatlang::Lang>,
15    /// Limit of result objects.
16    pub limit: Option<usize>,
17    /// The number of result objects we want to skip.
18    pub offset: Option<usize>,
19}
20
21impl QueryRequest {
22    /// Creates base query request.
23    pub fn new(dest: Dest, terms: impl ToString) -> Self {
24        Self {
25            dest,
26            terms: terms.to_string(),
27            lang: None,
28            limit: None,
29            offset: None,
30        }
31    }
32
33    /// Set a language for the request.
34    pub fn lang(mut self, lang: whatlang::Lang) -> Self {
35        self.lang = Some(lang);
36        self
37    }
38
39    /// Set a limit for the request.
40    pub fn limit(mut self, limit: usize) -> Self {
41        self.limit = Some(limit);
42        self
43    }
44
45    /// Set an offset for the request.
46    pub fn offset(mut self, offset: usize) -> Self {
47        self.offset = Some(offset);
48        self
49    }
50
51    /// Set the pagination for the request. Automatic offset calculation based on provided
52    /// limit and page.
53    ///
54    /// Note: the first page is 0;
55    pub fn pag(self, page: usize, limit: usize) -> Self {
56        let offset = page * limit;
57        self.offset(offset).limit(limit)
58    }
59}
60
61#[derive(Debug)]
62pub struct QueryCommand {
63    pub(crate) req: QueryRequest,
64}
65
66impl StreamCommand for QueryCommand {
67    type Response = Vec<String>;
68
69    fn request(&self) -> protocol::Request {
70        let dest = &self.req.dest;
71        let lang = self
72            .req
73            .lang
74            .or_else(|| {
75                whatlang::detect(&self.req.terms)
76                    .and_then(|i| (i.confidence() == 1.0).then(|| i.lang()))
77            })
78            .map(|l| l.code());
79
80        protocol::Request::Query {
81            collection: dest.collection().clone(),
82            bucket: dest
83                .bucket_opt()
84                .cloned()
85                .unwrap_or_else(|| String::from("default")),
86            terms: self.req.terms.clone(),
87            offset: self.req.offset,
88            limit: self.req.limit,
89            lang,
90        }
91    }
92
93    fn receive(&self, res: protocol::Response) -> Result<Self::Response> {
94        if let protocol::Response::Event(protocol::EventKind::Query, _id, objects) = res {
95            Ok(objects)
96        } else {
97            Err(Error::WrongResponse)
98        }
99    }
100}