javascript - Firestore 嵌套文档在集合文档中具有随机 ID

标签 javascript firebase google-cloud-firestore

我正在使用 Angular 和 firebase 创建一个应用程序。我想在该集合中创建一个名为 PETS 的集合,文档 ID 将是当前登录的用户 UID。在该文档中,我想根据我的表单值创建具有随机 ID 的文档。

-|pets
   -|userId
        -|RandomId which contains all the form values
        -|RandomId which contains all the form values

我现在正在使用这个方法。请告诉我这里需要进行哪些更改。此方法创建与当前用户具有相同 ID 的集合。但它不会使用用户 ID 在父文档中创建单独的文档。另外,我想用随机 ID 循环遍历这些文档,并在前面显示 PETS 列表。

addPet(ownerName, PetName, type, breed, size){
    let user = this.afAuth.auth.currentUser;
    if (user) {
      return new Promise((resolve, reject) => {
        this.afs.collection("pets").doc(user.uid).set({
          OwnerName: ownerName,
          Petname: PetName,
          PetType: type,
          PetBreed: breed,
          PetSize: size
        })
        .then((response) => {
            resolve(response)
        })
        .catch((error) => {
            reject(error)
        });
      })
    } else {
        alert('user not logged in')
    }
  }

最佳答案

当前您希望将用户的宠物存储在 /pets/userId 中。要在此位置添加每只宠物,您需要使用子集合,因为文档不能容纳其他文档。以下代码添加了一个宠物,该宠物将存储在 /pets/userId/pets/somePetId 中。

addPet(ownerName, petName, type, breed, size){
    let user = this.afAuth.auth.currentUser;
    if (!user) {
      return Promise.reject({code: 'unauthenticated', message: 'user not logged in'})
    }
    return this.afs.collection("pets").doc(user.uid).collection("pets").add({
        OwnerName: ownerName,
        OwnerID: user.uid,
        PetName: petName,
        PetType: type,
        PetBreed: breed,
        PetSize: size
      });
  }

但是,您还有另外两种方法可以对此数据进行建模。

全局宠物收藏

不是将宠物保存在 userId 下,而是每只宠物都有自己的 ID,并且您可以将该宠物链接到其主人的 ID。

addPet(ownerName, petName, type, breed, size){
    let user = this.afAuth.auth.currentUser;
    if (!user) {
      return Promise.reject({code: 'unauthenticated', message: 'user not logged in'})
    }
    return this.afs.collection("pets").add({
        OwnerName: ownerName,
        OwnerID: user.uid,
        PetName: petName,
        PetType: type,
        PetBreed: breed,
        PetSize: size
      });
  }

要获取给定用户的宠物数组,您可以使用以下命令:

function getPetsForCurrentUser() {
  let user = this.afAuth.auth.currentUser;
  if (!user) {
    return Promise.reject({code: 'unauthenticated', message: 'user not logged in'})
  }
  return this.afs.collection("pets").where("OwnerID", '==', user.uid).get()
    .then(childrenAsArrayOfObjects)
}

用户的宠物子集合

由于您使用的是 Cloud Firestore 而不是实时数据库,因此您可以将每只宠物保存为所有者用户数据的子集合。与实时数据库不同,当您获取 /users/userId 的数据时,您只能获取该特定文档的数据,而不是嵌套在该路径下的所有数据。下面的代码为每只宠物分配自己的 ID,并将其保存到其所有者的子集合中:

addPet(ownerName, petName, type, breed, size){
    let user = this.afAuth.auth.currentUser;
    if (!user) {
      return Promise.reject({code: 'unauthenticated', message: 'user not logged in'})
    }
    return this.afs.collection("users").doc(user.uid).collection("pets").add({
        OwnerName: ownerName,
        OwnerID: user.uid,
        PetName: petName,
        PetType: type,
        PetBreed: breed,
        PetSize: size
      });
  }

要获取给定用户的宠物数组,您可以使用以下命令:

function getPetsForCurrentUser() {
  let user = this.afAuth.auth.currentUser;
  if (!user) {
    return Promise.reject({code: 'unauthenticated', message: 'user not logged in'})
  }
  return this.afs.collection("users").doc(user.uid).collection("pets").get()
    .then(childrenAsArrayOfObjects)
}

使用这个数据结构,如果您想查询所有宠物,无论它们的主人是谁,您都可以使用 collection group query .

let ragdollCatsQuery = db.collectionGroup('pets').where('PetType', '==', 'Cat').where('PetBreed', '==', 'Ragdoll');
ragdollCatsQuery.get()
  .then(querySnapshot => {
    console.log("Found " + querySnapshot.size + " cats with the breed: Ragdoll");
  })

其他说明

请使用一致的大小写样式,以防止错误和拼写错误。例如将 Petname 更改为 PetName 以匹配数据库键 OwnerName 的 TitleCase。同样,变量名称的约定是使用驼峰式命名法,因此变量 PetName 应为 petName

以上函数均使用以下转换函数:

function childrenAsArrayOfObjects(querySnapshot, idFieldName) {
  let idFieldName = (idFieldName && idFieldName + "") || "id";
  let children = [];
  querySnapshot.forEach(childDoc => {
    children.push({...childDoc.data(), [idFieldName]: childDoc.id})
  }
  return children;
}

如果您想在使用此转换时对文档 ID 使用不同的字段名称,您可以使用:

.then(querySnapshot => childrenAsArrayOfObjects(querySnapshot, "PetID"))

您可以找到其他转换here .

关于javascript - Firestore 嵌套文档在集合文档中具有随机 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59546879/

相关文章:

javascript - 从 php 制作的数组中提取数据并将其传递给 javascript twig

javascript - 未捕获的语法错误 : await is only valid in async function (its in an async function though. ...)

javascript - 传递 key 会导致我的 firebase URL 中出现多余字符,如何删除它们?

firebase - 动态链接 - 正在发布域和路径前缀。请在 1 个月后重试

java - 如何从具有嵌套子项的 firebase 检索 json?

Javascript:Cloud Firestore 合并正在替换数据

javascript - 在 igEditor 中输入基本元素时 listItems 不起作用

javascript - 在 React 中嵌套状态是不好的做法吗?

google-cloud-platform - 从 Google Cloud Datastore 导出的关键属性上的应用 ID 设置为 b~<app_id>。这使得导入不可用

Firebase/Firestore 用户访问权限和角色如何运作?