Firebase - Cloud Functions - 对集合进行查询

Posted

技术标签:

【中文标题】Firebase - Cloud Functions - 对集合进行查询【英文标题】:Firebase - Cloud Functions - make queries on collection 【发布时间】: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;
    
);

谁能帮我解决这个问题?

【问题讨论】:

【参考方案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) 子句是否必要? 主要是因为故事查询没有结果。

以上是关于Firebase - Cloud Functions - 对集合进行查询的主要内容,如果未能解决你的问题,请参考以下文章

保护 Firebase Cloud Function HTTP 端点

是否可以检索 Firebase Cloud Function 源代码?

在 Cloud Function for Firebase 中设置 Firebase 消息的优先级

Firebase Cloud Function 部署 tslint 错误

Firebase 中的 Function Cloud 是不是免费(Cloud Functions 部署需要按需付费 (Blaze) 计费方案)

如何直接从您的 Angular 项目中调用 Firebase Cloud Function