firestore 0.59.1

Library provides a simple API for Google Firestore and own Serde serializer based on efficient gRPC API
Documentation

Cargo tests and formatting security audit

Firestore for Rust

Library provides a simple API for Google Firestore based on the official gRPC API:

  • Fluent high-level and strongly typed API, the only public API of this library;
  • Create or update documents using Rust structures and Serde;
  • Support for:
    • Querying/streaming docs/objects;
    • Listing documents/objects (stream_all follows the page tokens for you);
    • Listening changes from Firestore;
    • Transactions;
    • Aggregated queries: count, sum, avg;
    • Streaming batch writes with automatic throttling to stay under the Firestore write rate limits;
    • K-nearest neighbor (KNN) vector search with Euclidean, Cosine and Dot Product measures;
    • Query cursors and partition queries;
    • Collection group queries and listing collection IDs;
    • Server side document transforms: increment, array append/remove, server timestamp;
    • Update/delete preconditions;
    • Consistency selectors to read at a given time or inside a transaction;
    • Explaining queries;
    • Request tags to attribute Firestore usage;
  • Full async based on Tokio runtime;
  • Macros that help you use your structure fields as Firestore field paths;
  • Implements own Serde serializer to Firestore protobuf values;
  • Support for multiple database IDs;
  • Support for extended datatypes:
    • Firestore timestamp as a FirestoreTimestamp type or with #[serde(with)] attributes (based on jiff);
    • Lat/Lng;
    • References;
    • Explicit nulls;
  • Caching support for collections and documents:
    • In-memory cache;
    • Persistent cache;
  • Declarative index management behind an opt-in admin feature: composite indexes, vector indexes, single-field overrides and TTL policy, planned and synced with one call;
  • Bulk delete behind the same admin feature: removes every document in named collection groups, at any depth across the whole database, in the background;
  • Works with the Firestore emulator through FIRESTORE_EMULATOR_HOST, no credentials needed;
  • Google client based on gcloud-sdk library that automatically detects GCE environment or application default accounts for local development;

Documentation

Please follow to the official website: https://firestore-rust.abdolence.dev.

Upgrading from an older version? See the migration guide.

Quick start

Cargo.toml:

[dependencies]
firestore = "0.58"
use firestore::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Deserialize, Serialize)]
struct MyTestStructure {
    some_id: FirestoreDocumentId,
    some_string: String,
    some_num: u64,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let db = FirestoreDb::new("my-project-id").await?;

    const TEST_COLLECTION_NAME: FirestoreCollectionId =
        FirestoreCollectionId::from_static("test");

    let my_struct = MyTestStructure {
        some_id: FirestoreDocumentId::from_static("test-1"),
        some_string: "Test".to_string(),
        some_num: 42,
    };

    // Create
    let object_returned: MyTestStructure = db.fluent()
        .insert()
        .into(TEST_COLLECTION_NAME)
        .document_id(&my_struct.some_id)
        .object(&my_struct)
        .execute()
        .await?;

    // Update or create
    // (Firestore supports creating documents with update if you provide the document ID).
    let object_updated: MyTestStructure = db.fluent()
        .update()
        .fields(paths!(MyTestStructure::{some_num, some_string}))
        .in_col(TEST_COLLECTION_NAME)
        .document_id(&my_struct.some_id)
        .object(&MyTestStructure {
            some_num: my_struct.some_num + 1,
            some_string: "updated-value".to_string(),
            ..my_struct.clone()
        })
        .execute()
        .await?;

    // Get object by id
    let find_it_again: Option<MyTestStructure> = db.fluent()
        .select()
        .by_id_in(TEST_COLLECTION_NAME)
        .obj()
        .one(&my_struct.some_id)
        .await?;

    // Query
    let as_vec: Vec<MyTestStructure> = db.fluent()
        .select()
        .fields(paths!(MyTestStructure::{some_id, some_num, some_string}))
        .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"),
            ])
        })
        .order(|o| o.fields([o.field(path!(MyTestStructure::some_num)).desc()]))
        .obj()
        .query()
        .await?;

    // Delete data
    db.fluent()
        .delete()
        .from(TEST_COLLECTION_NAME)
        .document_id(&my_struct.some_id)
        .execute()
        .await?;

    println!("{object_returned:?} {object_updated:?} {find_it_again:?} {as_vec:?}");

    Ok(())
}

If you see no process-level CryptoProvider available, see Crypto provider error.

Examples

All examples available in the examples directory.

To run an example with environment variables:

PROJECT_ID=<your-google-project-id> cargo run --example crud

Google authentication

Looks for credentials in the following places, preferring the first location found:

  • A JSON file whose path is specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable.
  • A JSON file in a location known to the gcloud command-line tool using gcloud auth application-default login.
  • On Google Compute Engine, it fetches credentials from the metadata server.

For local development don't confuse gcloud auth login with gcloud auth application-default login, since the first authorize only gcloud tool to access the Cloud Platform. See Google authentication for the details.

Other credentials go through FirestoreDb::with_options_auth, which takes the google-cloud-auth credentials gcloud-sdk re-exports, or a GoogleAuthHeaders. The library re-exports gcloud-sdk as firestore::gcloud_sdk, so these types need no gcloud-sdk dependency of your own. See Client instance and lifecycle for the examples.

Upgrading to 0.58

0.58 moves to gcloud-sdk 0.33, which mints the tokens with google-cloud-auth:

  • FirestoreDb::with_options_token_source and the gcloud-sdk token sources are removed, FirestoreDb::with_options_auth replaces them;
  • FirestoreDb::new, with_options and with_options_service_account_key_file keep their signatures;
  • gcloud-sdk is re-exported as firestore::gcloud_sdk;
  • the new default feature auth-default-crypto brings the crypto provider service account keys sign with;
  • the MSRV is 1.91.

See the migration guide for the details.

How this library is tested

There are integration tests in the tests directory that runs for every commit against the real Firestore instance allocated for testing purposes. Be aware not to introduce huge document reads/updates and collection isolation from other tests.

Licence

Apache Software License (ASL)

Author

Abdulla Abdurakhmanov