use crate::{
Client, Error, execute_wrapper,
models::{DocumentIndexParameters, SearchResult},
traits,
};
use ::std::borrow::Cow;
use serde::{Serialize, de::DeserializeOwned};
use typesense_codegen::{
apis::documents_api,
models::{
self as raw_models, DeleteDocumentsParameters, ExportDocumentsParameters,
ImportDocumentsParameters, UpdateDocumentsParameters,
},
};
pub struct Documents<'d, D = serde_json::Value>
where
D: DeserializeOwned + Serialize,
{
client: &'d Client,
collection_name: &'d str,
_phantom: core::marker::PhantomData<D>,
}
impl<'d, D> Documents<'d, D>
where
D: DeserializeOwned + Serialize,
{
#[inline]
pub(super) fn new(client: &'d Client, collection_name: &'d str) -> Self {
Self {
client,
collection_name,
_phantom: core::marker::PhantomData,
}
}
async fn index(
&self,
document: serde_json::Value,
action: &str,
params: Option<DocumentIndexParameters>,
) -> Result<serde_json::Value, Error<documents_api::IndexDocumentError>> {
let params = documents_api::IndexDocumentParams {
collection_name: self.collection_name.into(),
body: document,
action: Some(action.into()),
dirty_values: params.and_then(|d| d.dirty_values), };
execute_wrapper!(self, documents_api::index_document, params)
}
pub async fn import_jsonl(
&self,
documents_jsonl: impl Into<Cow<'_, str>>,
params: ImportDocumentsParameters,
) -> Result<String, Error<documents_api::ImportDocumentsError>> {
let params = documents_api::ImportDocumentsParams {
body: documents_jsonl.into(),
collection_name: self.collection_name.into(),
action: params.action,
batch_size: params.batch_size,
dirty_values: params.dirty_values,
remote_embedding_batch_size: params.remote_embedding_batch_size,
return_doc: params.return_doc,
return_id: params.return_id,
};
execute_wrapper!(self, documents_api::import_documents, params)
}
pub async fn export_jsonl(
&self,
params: ExportDocumentsParameters<'_>,
) -> Result<String, Error<documents_api::ExportDocumentsError>> {
let params = documents_api::ExportDocumentsParams {
collection_name: self.collection_name.into(),
exclude_fields: params.exclude_fields,
filter_by: params.filter_by,
include_fields: params.include_fields,
};
execute_wrapper!(self, documents_api::export_documents, params)
}
pub async fn delete(
&self,
params: DeleteDocumentsParameters<'_>,
) -> Result<raw_models::DeleteDocuments200Response, Error<documents_api::DeleteDocumentsError>>
{
let params = documents_api::DeleteDocumentsParams {
collection_name: self.collection_name.into(),
filter_by: Some(params.filter_by),
batch_size: params.batch_size,
ignore_not_found: params.ignore_not_found,
truncate: params.truncate,
};
execute_wrapper!(self, documents_api::delete_documents, params)
}
pub async fn search(
&self,
params: raw_models::SearchParameters<'_>,
) -> Result<SearchResult<D>, Error<documents_api::SearchCollectionError>> {
let search_params = documents_api::SearchCollectionParams {
collection_name: self.collection_name.into(),
cache_ttl: params.cache_ttl,
conversation: params.conversation,
conversation_id: params.conversation_id,
conversation_model_id: params.conversation_model_id,
drop_tokens_mode: params.drop_tokens_mode,
drop_tokens_threshold: params.drop_tokens_threshold,
enable_highlight_v1: params.enable_highlight_v1,
enable_curations: params.enable_curations,
enable_synonyms: params.enable_synonyms,
enable_typos_for_alpha_numerical_tokens: params.enable_typos_for_alpha_numerical_tokens,
enable_typos_for_numerical_tokens: params.enable_typos_for_numerical_tokens,
exclude_fields: params.exclude_fields,
exhaustive_search: params.exhaustive_search,
facet_by: params.facet_by,
facet_query: params.facet_query,
facet_return_parent: params.facet_return_parent,
facet_strategy: params.facet_strategy,
filter_by: params.filter_by,
filter_curated_hits: params.filter_curated_hits,
group_by: params.group_by,
group_limit: params.group_limit,
group_missing_values: params.group_missing_values,
hidden_hits: params.hidden_hits,
highlight_affix_num_tokens: params.highlight_affix_num_tokens,
highlight_end_tag: params.highlight_end_tag,
highlight_fields: params.highlight_fields,
highlight_full_fields: params.highlight_full_fields,
highlight_start_tag: params.highlight_start_tag,
include_fields: params.include_fields,
infix: params.infix,
limit: params.limit,
max_candidates: params.max_candidates,
max_extra_prefix: params.max_extra_prefix,
max_extra_suffix: params.max_extra_suffix,
max_facet_values: params.max_facet_values,
max_filter_by_candidates: params.max_filter_by_candidates,
min_len_1typo: params.min_len_1typo,
min_len_2typo: params.min_len_2typo,
num_typos: params.num_typos,
offset: params.offset,
curation_tags: params.curation_tags,
page: params.page,
per_page: params.per_page,
pinned_hits: params.pinned_hits,
pre_segmented_query: params.pre_segmented_query,
prefix: params.prefix,
preset: params.preset,
prioritize_exact_match: params.prioritize_exact_match,
prioritize_num_matching_fields: params.prioritize_num_matching_fields,
prioritize_token_position: params.prioritize_token_position,
q: params.q,
query_by: params.query_by,
query_by_weights: params.query_by_weights,
remote_embedding_num_tries: params.remote_embedding_num_tries,
remote_embedding_timeout_ms: params.remote_embedding_timeout_ms,
search_cutoff_ms: params.search_cutoff_ms,
snippet_threshold: params.snippet_threshold,
sort_by: params.sort_by,
split_join_tokens: params.split_join_tokens,
stopwords: params.stopwords,
synonym_num_typos: params.synonym_num_typos,
synonym_prefix: params.synonym_prefix,
text_match_type: params.text_match_type,
typo_tokens_threshold: params.typo_tokens_threshold,
use_cache: params.use_cache,
vector_query: params.vector_query,
voice_query: params.voice_query,
nl_model_id: params.nl_model_id,
nl_query: params.nl_query,
enable_analytics: params.enable_analytics,
synonym_sets: params.synonym_sets,
};
execute_wrapper!(self, documents_api::search_collection, search_params)
}
}
impl<'d, D> Documents<'d, D>
where
D: traits::Document,
{
pub async fn create(
&self,
document: &D,
params: Option<DocumentIndexParameters>,
) -> Result<D, Error<documents_api::IndexDocumentError>> {
let doc_value = serde_json::to_value(document)?;
let result_value = self.index(doc_value, "create", params).await?;
serde_json::from_value(result_value).map_err(Error::from)
}
pub async fn upsert(
&self,
document: &D,
params: Option<DocumentIndexParameters>,
) -> Result<D, Error<documents_api::IndexDocumentError>> {
let doc_value = serde_json::to_value(document)?;
let result_value = self.index(doc_value, "upsert", params).await?;
serde_json::from_value(result_value).map_err(Error::from)
}
pub async fn update(
&self,
document: &D::Partial,
params: UpdateDocumentsParameters<'_>,
) -> Result<raw_models::UpdateDocuments200Response, Error<documents_api::UpdateDocumentsError>>
{
let params = documents_api::UpdateDocumentsParams {
collection_name: self.collection_name.into(),
filter_by: params.filter_by,
body: document,
};
execute_wrapper!(self, documents_api::update_documents, params)
}
}