【问题标题】:Firebase - Cloud Functions - make queries on collectionFirebase - Cloud Functions - 对集合进行查询
【发布时间】:2019-04-16 03:07:49
【问题描述】:

假设我有两个包含用户和故事的顶级集合。现在,每次来自用户的文档得到更新(仅值 usernamephotoUrl),我想更新故事集合中文档的这些属性。

一个用户文档可能如下所示(缩短):

{
    username: 'blubber',
    photoUrl: 'my/photo/path',
    uid: 'usersUniqueId'
}

故事文档可能如下所示(缩短):

{
    username: 'blubber',
    photoUrl: 'my/photo/path',
    uid: 'usersUniqueId',
    sid: 'storiesUniqueId,
    content: '...'
}

现在是云功能部分。我现在不知道如何从包含用户 ID 的故事集合中查询所有文档。现在的代码如下所示:

export const onUpdateUser = functions.firestore.document('/users/{userId}')
    .onUpdate((change, context) => {
    const before = change.before.data();
    const after = change.after.data();

    if(before.username !== after.username || before.photoURL !== after.photoURL) {
        return admin.firestore().collection('/stories/')
               .where(before.uid, '==', ***fetch the comparison***)
        // do something
    } else {
        return null;
    }
});

谁能帮我解决这个问题?

【问题讨论】:

    标签: typescript firebase google-cloud-firestore google-cloud-functions


    【解决方案1】:

    我相信,这就是您想要实现的目标。

    我刚刚将函数调用与.onUpdate 调用中的引用分开。由于您没有明确说明,我还假设您将更新 stories 集合中的多个文档,为此,我们使用 batch

    const onUpdateUser = functions
      .firestore
      .document('/users/{userID}')
      .onUpdate(myFunc);
    
    const myFunc = (change, context) => {
      const before = change.before.data();
      const after = change.after.data();
    
      // Nothing changed, so exiting the cloud function early.
      if (before.username === after.username
        && before.photoURL === after.photoURL) {
        return Promise.resolve();
      }
    
      return admin
        .firestore()
        .collection('stories')
        .where('uid', '==', before.uid)
        .get()
        .then((docs) => {
          const batch = admin.firestore().batch();
    
          docs.forEach((doc) => {
            batch.set(doc.ref, {
              username: after.username,
              photoURL: after.photoURL,
            }, {
                // Merges the fields rather than replacing the 
                // whole document data
                merge: true,
            });
          });
    
          return batch.commit();
        })
        .catch(console.error);
    };
    

    【讨论】:

    • 似乎工作得很好,就像千斤顶接近!谢谢!还有一个问题:返回 Promise.resolve() 或返回 null 退出函数一样,对吧?
    • @Fantasia Cloud 在后台运行的函数期望得到一个 Promise 作为回报。如果返回 null,您可能会在每次调用时收到错误 Function returned undefined, expected Promise or value
    • 奇怪,因为 doug stevenson,google advocat 还建议在函数应该完成时返回 null。而且我猜 null 可以分配给任何类型。来源:youtube.com/watch?v=Bdm7QNwSHOg&t=120s
    • @幻想曲。看来我错过了。根据 Doug 的建议,我认为返回 Promisenull 应该可行。
    【解决方案2】:

    更新了下面的代码。几乎拥有它。我添加了异步等待,因为它会使代码更清晰,你会想要添加错误处理等。

    export const onUpdateUser = functions.firestore.document('/users/{userId}')
        .onUpdate(async (change, context) => {
        const before = change.before.data();
        const after = change.after.data();
    
        if (before.username !== after.username || before.photoURL !== after.photoURL) {
            return admin.firestore().collection('/stories/')
               .where('uid', '==', before.uid).get().then(  
                   result => {
                       if (result.size > 0) {
                           result.forEach(async doc => {
                               await doc.ref.update({
                                   username: after.username,
                                   photoUrl: after.photoUrl
                               })
                            })
                       }
                       return;
                   }
               )
        } else {
            return null;
        }
    });
    

    【讨论】:

    • if (result.size > 0) 子句是否必要?
    • 主要是因为故事查询没有结果。
    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 2020-05-06
    • 2020-10-22
    • 2018-08-18
    • 1970-01-01
    • 2021-11-18
    • 2020-04-08
    • 1970-01-01
    相关资源
    最近更新 更多