#firestore #document-database #gcp #google-cloud #key-value-store #collection #object

tiny-firestore-odm

Google Firestore 的轻量级对象文档映射器,专注于键值对象存储使用模型

8 个版本

0.2.6 2021 年 10 月 23 日
0.2.5 2021 年 10 月 22 日
0.1.0 2021 年 10 月 12 日

#2258 in 数据库接口

MIT/Apache

45KB
860

tiny-firestore-odm

wokflow state crates.io docs.rs

tiny-firestore-odm 是 Firestore 的轻量级对象文档映射器。它构建在 firestore-serde(用于文档/对象转换)之上,并为 Firestore 的 集合 提供了 Rust 表示形式,以及创建/修改/删除它们的相应方法。

其意图不是提供 Firestore 的所有功能,而是提供一个围绕将 Firestore 作为任意 Rust 对象(序列化)集合的键值存储来使用的简化接口。

有关兼容的 Rust/GCP 堆栈,请参阅 Are We Google Cloud Yet?

用法

use google_authz::Credentials;
use tiny_firestore_odm::{Collection, Database, NamedDocument};
use serde::{Deserialize, Serialize};
use tokio_stream::StreamExt;

// Define our data model.
// Any Rust type that implements Serialize and Deserialize can be stored in a Collection.

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct ActorRole {
    actor: String,
    role: String,
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Movie {
    pub name: String,
    pub year: u32,
    pub runtime: u32,
    pub cast: Vec<ActorRole>,
}

#[tokio::main(flavor = "current_thread")]
async fn main() {
    // Use `google-authz` for credential discovery.
    let creds = Credentials::default().await;
    // Firestore databases are namespaced by project ID, so we need that too.
    let project_id = std::env::var("GCP_PROJECT_ID").expect("Expected GCP_PROJECT_ID env var.");

    // A Database is the main wrapper around a raw FirestoreClient.
    // It gives us a way to create Collections.
    let database = Database::new(creds.into(), &project_id).await;

    // A Collection is a reference to a Firestore collection, combined with a type.
    let movies: Collection<Movie> = database.collection("tiny-firestore-odm-example-movies");

    // Construct a movie to insert into our collection.
    let movie = Movie {
        name: "The Big Lebowski".to_string(),
        year: 1998,
        runtime: 117,
        cast: vec![
            ActorRole {
                actor: "Jeff Bridges".to_string(),
                role: "The Dude".to_string(),
            },
            ActorRole {
                actor: "John Goodman".to_string(),
                role: "Walter Sobchak".to_string(),
            },
            ActorRole {
                actor: "Julianne Moore".to_string(),
                role: "Maude Lebowski".to_string(),
            },
        ]
    };

    // Save the movie to the collection. When we insert a document with `create`, it is assigned
    // a random key which is returned to us if it is created successfully.
    let movie_id = movies.create(&movie).await.unwrap();

    // We can use the key that was returned to fetch the film.
    let movie_copy = movies.get(&movie_id).await.unwrap();
    assert_eq!(movie, movie_copy);

    // Alternatively, we can supply a string to use as the key, like this:
    movies.try_create(&movie, "The Big Lebowski").await.unwrap();

    // Then, we can retrieve it with the same string.
    let movie_copy2 = movies.get("The Big Lebowski").await.unwrap();
    assert_eq!(movie, movie_copy2);

    // To clean up, let's loop over documents in the collection and delete them.
    let mut result = movies.list();

    // List returns a `futures_core::Stream` of `NamedDocument` objects.
    while let Some(NamedDocument {name, ..}) = result.next().await {
        movies.delete(&name).await.unwrap();
    }
}

文档存在语义

提供了不同的方法来实现对文档是否存在的不同语义,如下表所示。

方法 对象存在时的行为 对象不存在时的行为
create 不适用(选择新键) 创建
create_with_key 错误 创建
try_create 不执行任何操作;返回 Ok(false) 创建;返回 Ok(true)
upsert 替换 创建
update 替换 错误
delete 删除 错误

局限性

该软件包旨在为将 Firestore 作为键值存储的工作流程设计,其中每个集合对应一个 Rust 类型(尽管一个 Rust 类型可能对应多个 Firestore 集合)。

目前不支持以下功能

  • 除键之外的其他查询
  • 只更新文档的一部分
  • 事务
  • 订阅更新

(我没有排除支持这些功能,但该软件包的目标不是全面支持所有 GCP 功能,而是一个小但有用的子集。)

运行测试

要运行此软件包中的单元测试,无需任何特殊设置。要这样做,请运行

cargo test --lib

此外,还有一些集成测试,用于测试与外部世界的交互功能。要使用这些测试,您必须提供谷歌云凭证。我建议为集成测试创建一个专门的谷歌云项目,因为Firestore是以项目为命名空间的,这样可以避免集成测试写入用于其他目的的数据库。

然后,设置两个环境变量

  • GOOGLE_APPLICATION_CREDENTIALS,包含磁盘上.json文件的绝对路径,该文件包含服务帐户凭证。您可以通过谷歌云控制台下载此文件。
  • GCP_PROJECT_ID,包含您希望使用的项目的名称。这通常与服务帐户JSON文件的project_id字段相同。

设置好这些后,您可以运行

cargo test

来运行所有单元和集成测试。

依赖项

~65MB
~1M SLoC