Cloud Firestore 数据模型

Cloud Firestore 是一种基于文档的 NoSQL 数据库。与 SQL 数据库不同的是,它没有表格或行的概念,而是将数据存储在文档中,并将文档组织为集合。

每个文档包含一组键值对。Cloud Firestore 经过优化,可用于存储小型文档的大型集合。

所有文档必须存储在集合中。文档可以包含子集合和嵌套对象,两者都可以包括原始字段(如字符串)或复杂对象(如列表)。

集合和文档是在 Cloud Firestore 中隐式创建的。只需将数据分配给集合中的文档即可。如果集合或文档不存在,Cloud Firestore 会创建一个。

文档

在 Cloud Firestore 中,存储单元是文档。文档是一个轻量级记录,包含映射到值的字段。每个文件都用一个名称进行标识。

代表用户 alovelace 的文档如下所示:

  • class alovelace

    first : "Ada"
    last : "Lovelace"
    born : 1815

文档中的复杂嵌套对象称为映射。例如,您可以使用映射组织上例中的用户名,如下所示:

  • class alovelace

    name :
        first : "Ada"
        last : "Lovelace"
    born : 1815

您可能会注意到文档看起来很像 JSON。实际上他们基本上都属于 JSON。但有稍许差异(例如,文档支持额外的数据类型,大小限制为 1 MB),但总体而言,您可以将文档视为轻量级 JSON 记录。

集合

文件存在于集合中,而集合只是文档的容器。例如,您可以使用一个 users 集合来包含您的各种用户,每个用户用一个文档来表示:

  • collections_bookmark users

    • class alovelace

      first : "Ada"
      last : "Lovelace"
      born : 1815

    • class aturing

      first : "Alan"
      last : "Turing"
      born : 1912

Cloud Firestore 是无架构的,所以您可以自由选择在每个文档中放置哪些字段以及在这些字段中存储哪些数据类型。同一集合中的文档可以全部包含不同的字段或在这些字段中存储不同类型的数据。但是,最好在多个文档中使用相同的字段和数据类型,以便您可以更轻松地查询文档。

集合只包含文档,不包含任何其他内容。它不能直接包含带有值的原始字段,也不能包含其他集合。(有关如何在 Cloud Firestore 中组织更复杂数据的说明,请参阅分层数据。)

集合中的文档名称是唯一的。您可以提供自己的密钥(例如用户 ID),或者可以让 Cloud Firestore 自动为您创建随机 ID(例如,通过调用 add())。

您无需“创建”或“删除”集合。在集合中创建第一个文档之后,集合就有了。如果删除集合中的所有文档,集合将不再存在。

引用

Cloud Firestore 中的每个文档都通过其在数据库中的位置唯一进行标识。之前的示例展示了集合 users 中的一个文档 alovelace。要在代码中引用此位置,您可以创建一个指向此位置的引用。

网页
var alovelaceDocumentRef = db.collection('users').doc('alovelace');
Swift
let alovelaceDocumentRef = db.collection("users").document("alovelace")
Objective-C
FIRDocumentReference *alovelaceDocumentRef =
    [[self.db collectionWithPath:@"users"] documentWithPath:@"alovelace"];
Android
DocumentReference alovelaceDocumentRef = db.collection("users").document("alovelace");
Java
// Reference to a document with id "alovelace" in the collection "users"
DocumentReference document = db.collection("users").document("alovelace");
Python
a_lovelace_ref = db.collection(u'users').document(u'alovelace')
Node.js
var alovelaceDocumentRef = db.collection('users').doc('alovelace');
Go
alovelaceRef := client.Collection("users").Doc("alovelace")
PHP
$document = $db->collection('users')->document('lovelace');

引用是一个轻量级对象,它仅指向数据库中的某个位置。无论此位置中是否存在数据,您都可以创建引用,并且创建引用不会执行任何网络操作。

您还可以创建对集合的引用:

网页
var usersCollectionRef = db.collection('users');
Swift
let usersCollectionRef = db.collection("users")
Objective-C
FIRCollectionReference *usersCollectionRef = [self.db collectionWithPath:@"users"];
Android
CollectionReference usersCollectionRef = db.collection("users");
Java
// Reference to the collection "users"
CollectionReference collection = db.collection("users");
Python
users_ref = db.collection(u'users')
Node.js
var usersCollectionRef = db.collection('users');
Go
usersRef := client.Collection("users")
PHP
$collection = $db->collection('users');

为方便起见,您还可以通过将文档或集合的路径指定为字符串来创建引用,路径组成部分之间以正斜杠 (/) 分隔。例如,要创建对 alovelace 文档的引用:

网页
var alovelaceDocumentRef = db.doc('users/alovelace');
Swift
let aLovelaceDocumentReference = db.document("users/alovelace")
Objective-C
FIRDocumentReference *aLovelaceDocumentReference =
    [self.db documentWithPath:@"users/alovelace"];
Android
DocumentReference alovelaceDocumentRef = db.document("users/alovelace");
Java
// Reference to a document with id "alovelace" in the collection "users"
DocumentReference document = db.document("users/alovelace");
Python
a_lovelace_ref = db.document(u'users/alovelace')
Node.js
var alovelaceDocumentRef = db.doc('users/alovelace');
Go
alovelaceRef := client.Doc("users/alovelace")
PHP
$document = $db->document('users/lovelace');

分层数据

要了解分层数据结构在 Cloud Firestore 中的工作原理,让我们以一个提供消息和聊天室功能的聊天应用来看一看。

您可以创建一个名为 rooms 的集合来存储不同的聊天室:

  • collections_bookmark rooms

    • class roomA

      name : "my chat room"

    • class roomB

      ...

现在您已经有聊天室了,就可以决定如何存储消息。您可能不想将它们存储在聊天室的文档中。这是因为 Cloud Firestore 中的文档应该是轻量级的,而聊天室可能包含大量消息。但是,您可以在聊天室的文档中创建额外的集合作为子集合。

子集合

在此情况下存储消息的最佳方法是使用子集合。子集合是指与特定文档相关联的集合。

您可以在 rooms 集合中为每个聊天室文档创建一个名为 messages 的子集合:

  • collections_bookmark rooms

    • class roomA

      name : "my chat room"

      • collections_bookmark messages

        • class message1

          from : "alex"
          msg : "Hello World!"

        • class message2

          ...

    • class roomB

      ...

在此示例中,您将使用以下代码在子集合中创建对消息的引用:

网页
var messageRef = db.collection('rooms').doc('roomA')
                .collection('messages').doc('message1');
Swift
let messageRef = db
    .collection("rooms").document("roomA")
    .collection("messages").document("message1")
Objective-C
FIRDocumentReference *messageRef =
    [[[[self.db collectionWithPath:@"rooms"] documentWithPath:@"roomA"]
    collectionWithPath:@"messages"] documentWithPath:@"message1"];
Android
DocumentReference messageRef = db
        .collection("rooms").document("roomA")
        .collection("messages").document("message1");
Java
// Reference to a document in subcollection "messages"
DocumentReference document =
    db.collection("rooms").document("roomA").collection("messages").document("message1");
Python
room_a_ref = db.collection(u'rooms').document(u'roomA')
message_ref = room_a_ref.collection(u'messages').document(u'message1')
Node.js
var messageRef = db.collection('rooms').doc('roomA')
    .collection('messages').doc('message1');
Go
messageRef := client.Collection("rooms").Doc("roomA").
	Collection("messages").Doc("message1")
PHP
$document = $db
    ->collection('rooms')
    ->document('roomA')
    ->collection('messages')
    ->document('message1');

请注意集合和文档的交替模式。您的集合和文档必须始终遵循此模式。您不能在集合中引用集合或在文档中引用文档。

子集合可用于分层组织数据,使数据更易于访问。要获取 roomA 中的所有消息,您可以只访问 db.collection('rooms').doc('roomA').collection('messages') 集合。

子集合中的文档也可以包含子集合,以便进一步嵌套数据。嵌套数据的深度最多可达 100 级。

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面