Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Nested collections

You can work with nested collections specifying path/location to a parent for documents. parent_path and the builder’s at also validate the collection name they are given, so a FirestoreCollectionId or a bad raw &str is caught in the same call rather than at the server.

use firestore::*;
use futures::stream::BoxStream;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)]
struct MyParentStructure { some_id: String }
#[derive(Debug, Clone, Deserialize, Serialize)]
struct MyChildStructure { some_id: String }
const TEST_PARENT_COLLECTION_NAME: &str = "nested-test";
const TEST_CHILD_COLLECTION_NAME: &str = "test-childs";
async fn example(
    db: FirestoreDb,
    parent_struct: MyParentStructure,
    child_struct: MyChildStructure,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Creating a parent doc
db.fluent()
    .insert()
    .into(TEST_PARENT_COLLECTION_NAME)
    .document_id(&parent_struct.some_id)
    .object(&parent_struct)
    .execute::<()>()
    .await?;

// The doc path where we store our children
let parent_path = db.parent_path(TEST_PARENT_COLLECTION_NAME, parent_struct.some_id)?;

// Create a child doc
db.fluent()
    .insert()
    .into(TEST_CHILD_COLLECTION_NAME)
    .document_id(&child_struct.some_id)
    .parent(&parent_path)
    .object(&child_struct)
    .execute::<()>()
    .await?;

// Listing children
println!("Listing all children");

let objs_stream: BoxStream<MyChildStructure> = db
    .fluent()
    .list()
    .from(TEST_CHILD_COLLECTION_NAME)
    .parent(&parent_path)
    .obj()
    .stream_all()
    .await?;
let _ = objs_stream;
Ok(())
}

Complete example available here.

You can nest multiple levels of collections using at():

use firestore::*;
const TEST_PARENT_COLLECTION_NAME: &str = "nested-test";
const TEST_CHILD_COLLECTION_NAME: &str = "test-childs";
const TEST_GRANDCHILD_COLLECTION_NAME: &str = "test-grandchilds";
fn example(db: &FirestoreDb) -> Result<(), Box<dyn std::error::Error>> {
let parent_path = db
    .parent_path(TEST_PARENT_COLLECTION_NAME, "parent-id")?
    .at(TEST_CHILD_COLLECTION_NAME, "child-id")?
    .at(TEST_GRANDCHILD_COLLECTION_NAME, "grand-child-id")?;
let _ = parent_path;
Ok(())
}