javascript - 使用 Firebase Cloud Functions 批量写入

标签 javascript node.js swift firebase google-cloud-functions

我使用 Firebase 作为 iOS 应用的后端,但不知道如何通过其云函数构建批量写入。

我的 Firestore 中有两个集合:饮料和顾客。每个新饮料和每个新客户都会分配一个 userId 属性,该属性与当前登录用户的 uid 相对应。此 userId 与对 Firestore 的查询一起使用,以仅获取与登录用户相关的饮料和客户,如下所示:Firestore.firestore().collection("customers")。 whereField("userId", isEqualTo: Auth.auth().currentUser.uid)

用户可以匿名登录,也可以匿名订阅。问题是,如果他们注销,就无法重新登录到同一个匿名 uid。 uid 还通过 RevenueCat SDK 存储为 appUserID,因此我仍然可以访问它,但由于我无法使用 uid 将用户重新登录到其匿名帐户,这是帮助用户的唯一方法。用户在恢复购买时访问其数据的方法是将其数据的 userId 字段从旧 uid 更新为新 uid。这就是需要批量写入的地方。

总的来说,我对编程还比较陌生,但对于 Cloud Functions、JavaScript 和 Node.js 来说,我非常新鲜。不过,我在网络上进行了研究,认为我找到了一个解决方案,可以创建一个可调用的云函数,并使用数据对象发送新旧用户 ID,查询具有旧用户 ID 的文档集合并更新其 userId 字段到新的。不幸的是它不起作用,我不明白为什么。

这是我的代码:

// Cloud Function

exports.transferData = functions.https.onCall((data, context) => {
  const firestore = admin.firestore();
  const customerQuery = firestore.collection('customers').where('userId', '==', `${data.oldUser}`);
  const drinkQuery = firestore.collection('drinks').where('userId', '==', `${data.oldUser}`);

  const customerSnapshot = customerQuery.get();
  const drinkSnapshot = drinkQuery.get();
  const batch = firestore.batch();

  for (const documentSnapshot of customerSnapshot.docs) {
    batch.update(documentSnapshot.ref, { 'userId': `${data.newUser}` });
  };
  for (const documentSnapshot of drinkSnapshot.docs) {
    batch.update(documentSnapshot.ref, { 'userId': `${data.newUser}` });
  };
  return batch.commit();
});
// Call from app

func transferData(from oldUser: String, to newUser: String) {
    let functions = Functions.functions()
    
    functions.httpsCallable("transferData").call(["oldUser": oldUser, "newUser": newUser]) { _, error in
        if let error = error as NSError? {
            if error.domain == FunctionsErrorDomain {
                let code = FunctionsErrorCode(rawValue: error.code)
                let message = error.localizedDescription
                let details = error.userInfo[FunctionsErrorDetailsKey]
                print(code)
                print(message)
                print(details)
            }
        }
    }
}

这是来自 Cloud Functions 日志的错误消息:

Unhandled error TypeError: customerSnapshot.docs is not iterable
    at /workspace/index.js:22:51
    at fixedLen (/workspace/node_modules/firebase-functions/lib/providers/https.js:66:41)
    at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:385:32
    at processTicksAndRejections (internal/process/task_queues.js:95:5)

据我了解,customerSnapshot 是一种称为 Promise 的东西,我猜这就是我无法迭代它的原因。到目前为止,我的知识太深了,不知道如何处理查询返回的这些 Promise。

我想我可以强制用户在订阅之前创建一个登录名,但既然我已经走到了这一步,这感觉就像是一个懦夫的出路。我宁愿同时拥有这两种选择并做出决定,而不是走一条被迫的道路。另外,如果我弄清楚了这一点,我将学习更多 JavaScript!

非常感谢任何和所有帮助!

编辑:

解决方案:

// Cloud Function

exports.transferData = functions.https.onCall(async(data, context) => {
  const firestore = admin.firestore();
  const customerQuery = firestore.collection('customers').where('userId', '==', `${data.oldUser}`);
  const drinkQuery = firestore.collection('drinks').where('userId', '==', `${data.oldUser}`);

  const customerSnapshot = await customerQuery.get();
  const drinkSnapshot = await drinkQuery.get();
  const batch = firestore.batch();

  for (const documentSnapshot of customerSnapshot.docs.concat(drinkSnapshot.docs)) {
    batch.update(documentSnapshot.ref, { 'userId': `${data.newUser}` });
  };
  
  return batch.commit();
});

最佳答案

正如您已经猜到的,调用 customerQuery.get() 返回一个 promise 。

为了了解您需要什么,您应该首先熟悉这里的 Promise 概念:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

对于您的用例,您可能最终会使用 then 回调:

customerQuery.get().then((result) => {
    // now you can access the result
}

或者通过使用 await 语句使方法调用同步:

const result = await customerQuery.get()
// now you can access the result

关于javascript - 使用 Firebase Cloud Functions 批量写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70747498/

相关文章:

javascript - 有没有什么很酷的方法来使用惰性求值序列来定义/计算 PI?

javascript - Q 返回已解决的 promise ?

带有 successHandler 的 Swift 函数调用带有 successHandler 的其他函数

swift - Tableview 一行创建五行?

javascript - 如何使一个类不可点击,直到它执行一个函数,然后再次使其可点击?

javascript - 字符串编码问题

javascript - 通过 AJAX 将 Rails 变量传递给部分?

javascript - 密码用html验证。获取请求重新加载页面而不是转到提交页面

css - Phantomjs 中的 Flexbox 支持可在 html2ng node.js 中使用

ios - 从其他 ViewController 调用方法 | swift