Skip to content

Commit

Permalink
Working explain()/explain_options() and an example
Browse files Browse the repository at this point in the history
  • Loading branch information
abdolence committed Apr 2, 2024
1 parent c4066dc commit d37a426
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 6 deletions.
98 changes: 98 additions & 0 deletions examples/explain-query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use chrono::{DateTime, Utc};
use firestore::*;
use futures::stream::BoxStream;
use futures::TryStreamExt;
use serde::{Deserialize, Serialize};

pub fn config_env_var(name: &str) -> Result<String, String> {
std::env::var(name).map_err(|e| format!("{}: {}", name, e))
}

// Example structure to play with
#[derive(Debug, Clone, Deserialize, Serialize)]
struct MyTestStructure {
some_id: String,
some_string: String,
one_more_string: String,
some_num: u64,
created_at: DateTime<Utc>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Logging with debug enabled
let subscriber = tracing_subscriber::fmt()
.with_env_filter("firestore=debug")
.finish();
tracing::subscriber::set_global_default(subscriber)?;

// Create an instance
let db = FirestoreDb::new(&config_env_var("PROJECT_ID")?).await?;

const TEST_COLLECTION_NAME: &'static str = "test-query";

if db
.fluent()
.select()
.by_id_in(TEST_COLLECTION_NAME)
.one("test-0")
.await?
.is_none()
{
println!("Populating a test collection");
let batch_writer = db.create_simple_batch_writer().await?;
let mut current_batch = batch_writer.new_batch();

for i in 0..500 {
let my_struct = MyTestStructure {
some_id: format!("test-{}", i),
some_string: "Test".to_string(),
one_more_string: "Test2".to_string(),
some_num: i,
created_at: Utc::now(),
};

// Let's insert some data
db.fluent()
.update()
.in_col(TEST_COLLECTION_NAME)
.document_id(&my_struct.some_id)
.object(&my_struct)
.add_to_batch(&mut current_batch)?;
}
current_batch.write().await?;
}

println!("Explain querying for a test collection as a stream using Fluent API");

// Query as a stream our data
let object_stream: BoxStream<FirestoreResult<FirestoreWithMetadata<MyTestStructure>>> = db
.fluent()
.select()
.fields(
paths!(MyTestStructure::{some_id, some_num, some_string, one_more_string, created_at}),
)
.from(TEST_COLLECTION_NAME)
.filter(|q| {
q.for_all([
q.field(path!(MyTestStructure::some_num)).is_not_null(),
q.field(path!(MyTestStructure::some_string)).eq("Test"),
Some("Test2")
.and_then(|value| q.field(path!(MyTestStructure::one_more_string)).eq(value)),
])
})
.order_by([(
path!(MyTestStructure::some_num),
FirestoreQueryDirection::Descending,
)])
.explain()
//.explain_options(FirestoreExplainOptions::new().with_analyze(true)) or with analyze
.obj()
.stream_query_with_metadata()
.await?;

let as_vec: Vec<FirestoreWithMetadata<MyTestStructure>> = object_stream.try_collect().await?;
println!("{:?}", as_vec);

Ok(())
}
6 changes: 5 additions & 1 deletion src/firestore_meta_doc.rs → src/firestore_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ impl TryFrom<RunQueryResponse> for FirestoreWithMetadata<Document> {
Ok(FirestoreWithMetadata {
document: value.document,
metadata: FirestoreDocumentMetadata {
transaction_id: Some(value.transaction),
transaction_id: if !value.transaction.is_empty() {
Some(value.transaction)
} else {
None
},
read_time: value.read_time.map(from_timestamp).transpose()?,
skipped_results: value.skipped_results as usize,
explain_metrics: value.explain_metrics.map(|v| v.try_into()).transpose()?,
Expand Down
40 changes: 37 additions & 3 deletions src/fluent_api/select_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use crate::select_aggregation_builder::FirestoreAggregationBuilder;
use crate::select_filter_builder::FirestoreQueryFilterBuilder;
use crate::{
FirestoreAggregatedQueryParams, FirestoreAggregatedQuerySupport, FirestoreAggregation,
FirestoreCollectionDocuments, FirestoreGetByIdSupport, FirestoreListenSupport,
FirestoreListener, FirestoreListenerParams, FirestoreListenerTarget,
FirestoreCollectionDocuments, FirestoreExplainOptions, FirestoreGetByIdSupport,
FirestoreListenSupport, FirestoreListener, FirestoreListenerParams, FirestoreListenerTarget,
FirestoreListenerTargetParams, FirestorePartition, FirestorePartitionQueryParams,
FirestoreQueryCollection, FirestoreQueryCursor, FirestoreQueryFilter, FirestoreQueryOrder,
FirestoreQueryParams, FirestoreQuerySupport, FirestoreResult, FirestoreResumeStateStorage,
FirestoreTargetType,
FirestoreTargetType, FirestoreWithMetadata,
};
use futures::stream::BoxStream;
use gcloud_sdk::google::firestore::v1::Document;
Expand Down Expand Up @@ -189,6 +189,25 @@ where
}
}

pub fn explain(self) -> FirestoreSelectDocBuilder<'a, D> {
Self {
params: self
.params
.with_explain_options(FirestoreExplainOptions::new()),
..self
}
}

pub fn explain_options(
self,
options: FirestoreExplainOptions,
) -> FirestoreSelectDocBuilder<'a, D> {
Self {
params: self.params.with_explain_options(options),
..self
}
}

#[inline]
pub fn obj<T>(self) -> FirestoreSelectObjBuilder<'a, D, T>
where
Expand Down Expand Up @@ -238,6 +257,12 @@ where
) -> FirestoreResult<BoxStream<'b, FirestoreResult<Document>>> {
self.db.stream_query_doc_with_errors(self.params).await
}

pub async fn stream_query_with_metadata<'b>(
self,
) -> FirestoreResult<BoxStream<'b, FirestoreResult<FirestoreWithMetadata<Document>>>> {
self.db.stream_query_doc_with_metadata(self.params).await
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -289,6 +314,15 @@ where
self.db.stream_query_obj_with_errors(self.params).await
}

pub async fn stream_query_with_metadata<'b>(
self,
) -> FirestoreResult<BoxStream<'b, FirestoreResult<FirestoreWithMetadata<T>>>>
where
T: 'b,
{
self.db.stream_query_obj_with_metadata(self.params).await
}

pub fn partition_query(self) -> FirestorePartitionQueryObjBuilder<'a, D, T>
where
T: 'a,
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ pub type FirestoreResult<T> = std::result::Result<T, FirestoreError>;

pub type FirestoreDocument = gcloud_sdk::google::firestore::v1::Document;

mod firestore_meta_doc;
mod firestore_meta;

pub use firestore_meta_doc::*;
pub use firestore_meta::*;

mod firestore_document_functions;

Expand Down

0 comments on commit d37a426

Please sign in to comment.