更新在Firebase中创建的集合(使用云功能)

问题描述:

请注意,以下方案使用Cloud Firestore更新在Firebase中创建的集合(使用云功能)

在我的云功能index.js,我有一个函数,createUserAccount,增加了一个新创建的用户到users收集,并为他们的电子邮件,照片,收藏领域(这是不需要的应用功能详细阐述)以及用户的其他不同领域。

// The following method has been simplified to focus on the problem statement 
public void createAccountWithEmailAndPassword(String username, String displayName, 
               String someOtherImportantThing) { 

    mFirebaseAuth.createUserWithEmailAndPassword(email, password) 
       .addOnCompleteListener(getActivity(), task -> { 
        if (task.isSuccessful()) { 
         Log.d(TAG, "createUserWithEmail:Success"); 
         onSuccess.updateAccount(displayName, username); 
         updateUsernameProperty(username); 
         onBackPressed(); 
        } else { 
          if (task.getException() != null) { 
           if (task.getException() 
             .getMessage() 
             .contains(EMAIL_EXISTS_ERROR)) { 
            // Handle Email Exists Error 
           } 
          } 
          Log.w(TAG, "createUserWithEmail:failure", 
            task.getException()); 
        } 
       }); 
    } 

正如你可以看到,当任务成功完成了几个方法被称为:该功能在下面的代码片段成功完成后触发updateUsernameProperty(String username)updateAccount(String displayName, username)

updateAccount(String displayName)需要选择一个用户displayName并将其作为字段添加到用户帐户。 这不会对用户集合进行更改 - 仅限于已验证的帐户

updateUsernameProperty(String username)以用户选择的用户名和将此属性设置为用户文档内的字段。下面是代码示例,因为它可能被证明有助于理解我的问题:

private void updateUsernameProperty(String username) { 
    DocumentReference docRef = mFirestore 
            .collection(TABLE_USERS) 
            .document(mFirebaseAuth.getUid()); 

    docRef.update(USERNAME_KEY, username) 
      .addOnSuccessListener(aVoid -> Log.d(TAG, "Username DocumentSnapshot Successful")) 
      .addOnFailureListener(e -> Log.e(TAG, "Error Updating Document: user/uid/username", e)); 
} 

到集合的典型路径是“用户/ {用户id} /用户名”

的问题:尝试更新用户文档中的用户名字段时,云功能createUserAccount尚未完成向数据库创建/添加新用户文档(即异步问题)。

我已经考虑使用rxJava2来帮助缓解这个问题,但我似乎无法包装我的头如何做到这一点。任何帮助是极大的赞赏。

如果您需要澄清一些事情,我会尽我所能提供所需的信息。

如果我理解正确的话,您有以下流程:

  1. 你叫createUserWithEmailAndPassword
  2. 云功能揭开序幕,并写入一些用户信息,以公司的FireStore
  3. 本地,您尝试更新用户信息包括 用户名。

但是,步骤2和步骤3是竞争条件,因为当您在客户端上发布更新时,云功能可能无法完成。

问题是update()调用取决于现有的文档。如果您在客户端代码和云端功能中使用set()呼叫与merge选项,则可以避免这种情况。

云功能

function createUserDoc(userId, data) { 
    var userRef = db.collection('users').doc(userId); 

    // Set the user document, creating it if it does not exist 
    // and merging with existing data if it does 
    return userRef.set(data, { merge: true }); 
} 

的Android代码

public void updateUsername(userId, username) { 
    Map<String, Object> data = new HashMap<>(); 
    data.put("username", username); 

    db.collection("users").document(userId) 
      .set(data, SetOptions.merge()); 
} 
+0

是的,这肯定是问题,而这个作品!我可以问你的意见: 我的应用程序允许用户创建一个唯一的用户名,并将这个值存储在一个随机UID的“用户名”集合中。然后,我添加两个字段,所有者的UID与实际用户名相匹配的“用户”文档和名称值。在“用户”文档中,我使用“用户名”集合中用户名的UID值更新了“用户名”字段。当我需要检查帐户创建时是否有用户名时,此方法是否有效? –

+0

@NP我不太了解你的情况,我认为这将是最简单的,如果你问这个关于*的新问题(我会很乐意回答) –

+0

我想知道是否有一种方法来查询所有集合中的可用文档。 (例如,存储在用户名集合中的所有文档只存储唯一的用户名)。 –