use std::sync::Arc;
use serde::Serialize;
use crate::{
Result,
client::AnytypeClient,
filters::Query,
http_client::{GetPaged, HttpClient},
prelude::*,
};
#[derive(Debug, Default, Serialize)]
struct SearchRequestBody {
#[serde(skip_serializing_if = "Option::is_none")]
query: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
types: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
sort: Option<Sort>,
#[serde(skip_serializing_if = "FilterExpression::is_empty")]
filters: FilterExpression,
}
#[derive(Debug)]
pub struct SearchRequest {
client: Arc<HttpClient>,
limit: Option<u32>,
offset: Option<u32>,
body: SearchRequestBody,
limits: ValidationLimits,
space_id: Option<String>,
}
impl SearchRequest {
pub(crate) fn new(
client: Arc<HttpClient>,
limits: ValidationLimits,
space_id: Option<String>,
) -> Self {
Self {
client,
limit: None,
offset: None,
body: SearchRequestBody::default(),
limits,
space_id,
}
}
#[must_use]
pub fn text(mut self, text: impl Into<String>) -> Self {
self.body.query = Some(text.into());
self
}
#[must_use]
pub fn limit(mut self, limit: u32) -> Self {
self.limit = Some(limit);
self
}
#[must_use]
pub fn offset(mut self, offset: u32) -> Self {
self.offset = Some(offset);
self
}
#[must_use]
pub fn types<S: Into<String>>(mut self, types: impl IntoIterator<Item = S>) -> Self {
self.body.types = types.into_iter().map(Into::into).collect();
self
}
#[must_use]
pub fn sort_asc(mut self, property: impl Into<String>) -> Self {
self.body.sort = Some(Sort::asc(property));
self
}
#[must_use]
pub fn sort_desc(mut self, property: impl Into<String>) -> Self {
self.body.sort = Some(Sort::desc(property));
self
}
#[must_use]
pub fn filter(mut self, filter: Filter) -> Self {
self.body.filters = FilterExpression::from(vec![filter]);
self
}
#[must_use]
pub fn filters(mut self, filters: FilterExpression) -> Self {
self.body.filters = filters;
self
}
pub async fn execute(self) -> Result<PagedResult<Object>> {
let query = Query::default()
.set_limit_opt(self.limit)
.set_offset_opt(self.offset);
if let Some(space_id) = self.space_id {
self.limits.validate_id(&space_id, "space_id")?;
self.client
.post_request_paged(
&format!("/v1/spaces/{}/search", &space_id),
&self.body,
query.into(),
)
.await
} else {
self.client
.post_request_paged("/v1/search", &self.body, query.into())
.await
}
}
}
impl AnytypeClient {
pub fn search_global(&self) -> SearchRequest {
SearchRequest::new(self.client.clone(), self.config.limits.clone(), None)
}
pub fn search_in(&self, space_id: impl Into<String>) -> SearchRequest {
SearchRequest::new(
self.client.clone(),
self.config.limits.clone(),
Some(space_id.into()),
)
}
}