use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use crate::{
error::EsError,
json::ShouldSkip,
operations::{
common::{OptionVal, Options},
format_indexes_and_types, ShardCountResult,
},
query::Query,
Client, EsResponse,
};
#[derive(Debug)]
pub struct CountURIOperation<'a, 'b> {
client: &'a mut Client,
indexes: &'b [&'b str],
doc_types: &'b [&'b str],
options: Options<'b>,
}
impl<'a, 'b> CountURIOperation<'a, 'b> {
pub fn new(client: &'a mut Client) -> CountURIOperation<'a, 'b> {
CountURIOperation {
client,
indexes: &[],
doc_types: &[],
options: Options::default(),
}
}
pub fn with_indexes(&'b mut self, indexes: &'b [&'b str]) -> &'b mut Self {
self.indexes = indexes;
self
}
pub fn with_types(&'b mut self, doc_types: &'b [&'b str]) -> &'b mut Self {
self.doc_types = doc_types;
self
}
pub fn with_query<S: Into<String>>(&'b mut self, qs: S) -> &'b mut Self {
self.options.push("q", qs.into());
self
}
add_option!(with_df, "df");
add_option!(with_analyzer, "analyzer");
add_option!(with_default_operator, "default_operator");
add_option!(with_lenient, "lenient");
add_option!(with_analyze_wildcard, "analyze_wildcard");
add_option!(with_terminate_after, "terminate_after");
pub fn send(&'b mut self) -> Result<CountResult, EsError> {
let url = format!(
"/{}/_count{}",
format_indexes_and_types(&self.indexes, &self.doc_types),
self.options
);
log::info!("Counting with: {}", url);
let response = self.client.get_op(&url)?;
match response.status_code() {
StatusCode::OK => Ok(response.read_response()?),
status_code => Err(EsError::EsError(format!(
"Unexpected status: {}",
status_code
))),
}
}
}
#[derive(Debug, Default, Serialize)]
struct CountQueryOperationBody<'b> {
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
query: Option<&'b Query>,
}
#[derive(Debug)]
pub struct CountQueryOperation<'a, 'b> {
client: &'a mut Client,
indexes: &'b [&'b str],
doc_types: &'b [&'b str],
options: Options<'b>,
body: CountQueryOperationBody<'b>,
}
impl<'a, 'b> CountQueryOperation<'a, 'b> {
pub fn new(client: &'a mut Client) -> Self {
CountQueryOperation {
client,
indexes: &[],
doc_types: &[],
options: Options::new(),
body: Default::default(),
}
}
pub fn with_indexes(&'b mut self, indexes: &'b [&'b str]) -> &'b mut Self {
self.indexes = indexes;
self
}
pub fn with_types(&'b mut self, doc_types: &'b [&'b str]) -> &'b mut Self {
self.doc_types = doc_types;
self
}
pub fn with_query(&'b mut self, query: &'b Query) -> &'b mut Self {
self.body.query = Some(query);
self
}
add_option!(with_df, "df");
add_option!(with_analyzer, "analyzer");
add_option!(with_default_operator, "default_operator");
add_option!(with_lenient, "lenient");
add_option!(with_analyze_wildcard, "analyze_wildcard");
add_option!(with_terminate_after, "terminate_after");
pub fn send(&'b mut self) -> Result<CountResult, EsError> {
let url = format!(
"/{}/_count{}",
format_indexes_and_types(&self.indexes, &self.doc_types),
self.options
);
let response = self.client.post_body_op(&url, &self.body)?;
match response.status_code() {
StatusCode::OK => Ok(response.read_response()?),
status_code => Err(EsError::EsError(format!(
"Unexpected status: {}",
status_code
))),
}
}
}
impl Client {
pub fn count_uri(&mut self) -> CountURIOperation {
CountURIOperation::new(self)
}
pub fn count_query(&mut self) -> CountQueryOperation {
CountQueryOperation::new(self)
}
}
#[derive(Debug, Deserialize)]
pub struct CountResult {
pub count: u64,
#[serde(rename = "_shards")]
pub shards: ShardCountResult,
}
#[cfg(test)]
mod tests {
use crate::tests::setup_test_data;
use crate::tests::{clean_db, make_client};
use crate::query::Query;
use super::CountResult;
#[test]
fn test_count_uri() {
let index_name = "test_count_uri";
let mut client = make_client();
clean_db(&mut client, index_name);
setup_test_data(&mut client, index_name);
let all_results: CountResult = client
.count_uri()
.with_indexes(&[index_name])
.send()
.unwrap();
assert_eq!(3, all_results.count);
let doc_1: CountResult = client
.count_uri()
.with_indexes(&[index_name])
.with_query("str_field:1ABC")
.send()
.unwrap();
assert_eq!(1, doc_1.count);
let not_found_doc: CountResult = client
.count_uri()
.with_indexes(&[index_name])
.with_query("str_field:lolol")
.send()
.unwrap();
assert_eq!(0, not_found_doc.count);
}
#[test]
fn test_count_query() {
let index_name = "test_count_query";
let mut client = make_client();
clean_db(&mut client, index_name);
setup_test_data(&mut client, index_name);
let all_results: CountResult = client
.count_query()
.with_indexes(&[index_name])
.with_query(&Query::build_match_all().build())
.send()
.unwrap();
assert_eq!(3, all_results.count);
let doc_1: CountResult = client
.count_query()
.with_indexes(&[index_name])
.with_query(
&Query::build_range("int_field")
.with_gte(2)
.with_lte(3)
.build(),
)
.send()
.unwrap();
assert_eq!(2, doc_1.count);
let not_found_doc: CountResult = client
.count_query()
.with_indexes(&[index_name])
.with_query(&Query::build_range("int_field").with_gte(99).build())
.send()
.unwrap();
assert_eq!(0, not_found_doc.count);
}
}