【问题标题】:How to update a single firebase firestore document如何更新单个 Firebase Firestore 文档
【发布时间】:2018-09-15 20:44:36
【问题描述】:

身份验证后,我尝试在 /users/ 中查找用户文档,然后我想使用来自 auth 对象的数据以及一些自定义用户属性来更新文档。但是我收到更新方法不存在的错误。有没有办法更新单个文档?所有 firestore 文档示例都假定您拥有实际的文档 ID,并且它们没有任何使用 where 子句查询的示例。

firebase.firestore().collection("users").where("uid", "==", payload.uid)
  .get()
  .then(function(querySnapshot) {
      querySnapshot.forEach(function(doc) {
          console.log(doc.id, " => ", doc.data());
          doc.update({foo: "bar"})
      });
 })

【问题讨论】:

  • 为什么不使用uid作为存储数据的实际文档ID呢?这让这个问题变得简单多了。
  • 这真是个好主意。这就是解决方案。由于典型应用程序数据库中的所有内容都将具有与特定用户相关的内容,这在许多关系数据库设计中很常见。我会为 firebase/firestore 推荐一个文档或教程。创建一个单独的 /users 集合并使其与 firebase Auth 用户保持同步并不是那么直观。
  • 我认为这里接受的答案是:stackoverflow.com/questions/55714423/… 是你要找的

标签: javascript firebase google-cloud-firestore


【解决方案1】:

您可以精确地执行以下操作(https://firebase.google.com/docs/reference/js/v8/firebase.firestore.DocumentReference):

var db = firebase.firestore();

db.collection("users").doc(doc.id).update({foo: "bar"});

【讨论】:

  • 如果您已经有了 uid,为什么还需要执行 get 请求?我们不是只需要那一行` db.collection("users").doc(doc.id).update({foo: "bar"});`
  • db.collection("users").doc(doc.id).update({foo: "bar"}) 是否同时算作读取和写入?在上面的示例中,仅使用doc.ref.update({foo: "bar"}) 会更划算吗?
  • 我们需要一个获取请求,因为uid != doc.id。例如,您可能使用了自动分配的文档 ID。
  • @themanatuf 、 db.collection("users").doc(doc.id).update({foo: "bar"})doc.ref.update({foo: "bar"}) 都应该算作一次写入。不过,您说得对,doc.ref 更好。更新答案,谢谢!
  • 我们如何在文档上使用 where 条件然后更新文档字段?请分享任何建议。谢谢。
【解决方案2】:

检查用户是否已经在那里,然后简单地.update,如果没有则.set

    var docRef = firebase.firestore().collection("users").doc(firebase.auth().currentUser.uid);
    var o = {};
    docRef.get().then(function(thisDoc) {
        if (thisDoc.exists) {
            //user is already there, write only last login
            o.lastLoginDate = Date.now();
            docRef.update(o);
        }
        else {
            //new user
            o.displayName = firebase.auth().currentUser.displayName;
            o.accountCreatedDate = Date.now();
            o.lastLoginDate = Date.now();
            // Send it
            docRef.set(o);
        }
        toast("Welcome " + firebase.auth().currentUser.displayName);
    });
}).catch(function(error) {
    toast(error.message);
});

【讨论】:

  • 没有理由做所有这些,因为如果记录不存在 set 将自动更新:firebase.google.com/docs/firestore/manage-data/add-data "如果文档不存在,它将被创建。如果文档存在,其内容将被新提供的数据覆盖,除非您指定数据应合并到现有文档中,如下所示:"
  • 那是 .set 方法。除非有更改,否则如果文档不存在,.update 将失败(与实时数据库不同,如果文档不存在,.update 将为您创建它。
  • 如果文档不存在,今天更新还会失败吗?
【解决方案3】:

在您的原始代码中更改此行

doc.update({foo: "bar"})

到这里

doc.ref.update({foo: "bar"})

应该工作

但更好的方法是使用批量写入: https://firebase.google.com/docs/firestore/manage-data/transactions#batched-writes

【讨论】:

    【解决方案4】:

    你只需要找到文档的官方ID,代码在这里!

        enter code here
        //Get user mail (logined)
        val db = FirebaseFirestore.getInstance()
        val user = Firebase.auth.currentUser
        val mail = user?.email.toString()
    
           //do update
           val update = db.collection("spending").addSnapshotListener { snapshot, e ->
                    val doc = snapshot?.documents
                    doc?.forEach {
                        //Assign data that I got from document (I neet to declare dataclass) 
                        val spendData= it.toObject(SpendDt::class.java)
                        if (spendData?.mail == mail) {
                            //Get document ID
                            val userId = it.id
                            //Select collection
                            val sfDocRef = db.collection("spendDocument").document(userId)
                            //Do transaction
                            db.runTransaction { transaction ->
                                val despesaConsum = hashMapOf(
                                    "medalHalfYear" to true,
                                )
                                //SetOption.merege() is for an existing document
                                transaction.set(sfDocRef, despesaConsum, SetOptions.merge())
                            }
                        }
    
                    }
                }
    }
    data class SpendDt(
        var oilMoney: Map<String, Double> = mapOf(),
        var mail: String = "",
        var medalHalfYear: Boolean = false
    )
    

    【讨论】:

      【解决方案5】:

      这样做的正确方法如下; 要在快照对象中进行任何数据操作,我们必须引用 .ref 属性

       firebase.firestore().collection("users").where("uid", "==", payload.uid)
        .get()
        .then(function(querySnapshot) {
            querySnapshot.forEach(function(doc) {
                console.log(doc.id, " => ", doc.data());
                doc.ref.update({foo: "bar"})//not doc.update({foo: "bar"})
            });
       })
      

      【讨论】:

        【解决方案6】:

        -- FIREBASE V9 更新--

        在较新版本的 Firebase 中,这样做是这样的:

        import { doc, updateDoc } from "firebase/firestore";
        
        const washingtonRef = doc(db, "cities", "DC");
        
        // Set the "capital" field of the city 'DC'
        await updateDoc(washingtonRef, {
          capital: true
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-07-27
          • 2021-02-05
          • 2019-02-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-25
          相关资源
          最近更新 更多