代码之家  ›  专栏  ›  技术社区  ›  Jonathan

具有完全对象匹配的Firestore“array contains”查询仍然不起作用

  •  0
  • Jonathan  · 技术社区  · 3 年前

    今天,我注意到我的代码中有一个错误,在我的Firestore中,没有对重复的数据执行某些清理操作。

    在不久前写这段代码时,我已经意识到对对象使用“array-converts”的挑剔本质。我知道它们需要有完全相同的形状。Firebase还按字母顺序插入所有带有键的对象(Maps),因此我甚至创建了一个辅助函数,以确保对象也按相同顺序具有键。

    export type UserReference = {
      name?: string;
      uid: AppUser['uid'];
    };
    
    export const getUserRef = (user: AppUser | DbUser): UserReference => ({
      name: user.name,
      uid: user.uid,
    });
    

    现在在我的代码中,它仍然不起作用。。。

     const linkedGroupQuery = getFirestore()
        .collection(constants.dbCollections.groups)
        .where('owners', 'array-contains', getUserRef(user));
    
    ...
    
     const querySnapshot = await linkedGroupQuery.get();
    
     querySnapshot.forEach((doc) => {
      const linkedGroup = doc.data() as DbGroup;
      const owners = linkedGroup.owners.filter((o) => o.uid !== uid);
      batch.update(doc.ref, { owners });
     });
    
    

    我可以在我的Firebase面板中看到,记录按预期插入,但此清理代码不起作用。

    同时,我有一个非常相似的代码,它确实有效:

        const groupRef: GroupReference = getGroupRef(group);
    
        const batch = getFirestore().batch();
    
        const usersWithGroup = await getFirestore()
          .collection(constants.dbCollections.users)
          .where('groups', 'array-contains', groupRef)
          .get();
    
        // Remove group from all users
        usersWithGroup.forEach((userSnapshot) => {
          const userData = userSnapshot.data() as DbUser;
          const userGroups = userData.groups?.filter((g) => g.id !== group.id);
          batch.update(userSnapshot.ref, { groups: userGroups });
        });
    
    

    这里可能发生了什么?

    编辑:
    事实证明,这是异步/等待和批处理写入的问题,而不是“数组包含”的问题

    0 回复  |  直到 3 年前
        1
  •  0
  •   Jonathan    3 年前

    今天,我学到了当您希望异步函数在另一个异步函数中执行,而不是在其他代码行之前执行时,使用wait的重要性。

    const batch = getFirestore().batch();
    
    ...
    
    // Await was missing here in this async helper
    await severGroupOwnerLinksWithUser(user.uid, batch);
    
    ...
    
    batch.commit();
    
    

    我已经编写了几个辅助函数,它们可以选择性地接受FirestoreWriteBatch。但是,由于这些函数是异步的,并且缺少wait关键字,所以它们在提交批处理之后运行。这导致了一些令人困惑的bug。由于这些异步操作的并行性,这些函数的某些部分确实有效,而其他部分则无效,因为它们依赖于已经提交的批处理。