【问题标题】:document.exists() returns false from firestoredocument.exists() 从 firestore 返回 false
【发布时间】:2018-10-04 01:25:30
【问题描述】:

我正在尝试检查 firestore 中的文档是否存在。我从 Firestore 控制台复制了文档 (col3) 的确切位置,因此它必须更正。

尽管文档保存在数据库中,但 document.exists() 返回 false。我从 this 站点遵循了 Google 指南。

我已经设置了断点并检查了 DocumentSnapshot 对象,但是很难遵循例如 zza、zzb、zzc...

private fun nameExists(userId: String, colName: String): Boolean{
    val nameExists = booleanArrayOf(false)
    val docRefA = fbDb!!.document("users/X9ogJzjJyOgGBV0kmzk7brcQXhz1/finalGrades/col3")

    val docRefB = fbDb!!.collection("users")
            .document(userId)
            .collection("finalGrades")
            .document(colName)


    docRefA.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val document = task.result
            if (document.exists()) {
                nameExists[0] = true
            }else{
                Log.d(TAG, "no such document")
            }
        } else {
            Log.d(TAG, "get failed with ", task.exception)
        }
    }
    return nameExists[0]
}

【问题讨论】:

  • 您能否显示 Firebase 控制台的屏幕截图以及您尝试加载的文档及其竞争路径?
  • @Frank van Puffelen - 澄清一下,我正在尝试获取文档,而不是加载。但是,我不关心 document.getData();我只对从 document.exists() 返回布尔值感兴趣;通知用户他们应该以不同的名称保存新文档。 screenshot 来自 Firestore。
  • 调用get() 加载文档数据。
  • Logcat 条目表明获取 DocumentReference 的操作是异步运行的,因此尽管在闭包中捕获了 nameExists[0] 中的值,但它在由 nameExists 返回后更新方法。 10-12 00:02:09.190 20519-20519/com.proto.patryk.ou_gradecalculator D/ModulesFragment:返回值 false ... 10-12 00:02:11.715 20519-20519/com. proto.patryk.ou_gradecalculator D/ModulesFragment:name 设置为 true 是否可以从 lambda 函数返回布尔值?
  • 哦,对不起,我完全错过了。 return nameExists[0] 确实没有办法工作,因为回调 black 还没有运行。这正是get() 使用完成侦听器本身来表示数据可用的原因。如果您需要确保有数据,您还需要传入一个完成侦听器(请参阅 here 了解另一个 Firebase 数据库,但问题和解决方案相同),或者您自己返回一个 Task

标签: android firebase google-cloud-firestore


【解决方案1】:

感谢@Frank van Puffelen 的提示,我能够调试代码。根据我的研究,以下代码是解决此类问题的经典方法。 也许有人会觉得它很有用。

第 1 步。 使用与要从异步操作返回的原始值或对象相同类型的参数定义功能接口。

interface OnMetaReturnedListener{
    fun onMetaReturned(colExists: Boolean)
}

第 2 步。创建一个将接口引用作为参数传递的方法。此方法将运行同步操作。检索到值后,调用函数式接口方​​法并将检索到的值/对象作为方法参数传递。

private fun nameExists(metaReturnedListener: OnMetaReturnedListener, colName: String){

    val userId = fbAuth!!.uid!!

    val docRefB: DocumentReference = fbDb!!.collection("users")
            .document(userId)
            .collection("finalGrades")
            .document(colName)

    docRefB.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val doc: DocumentSnapshot = task.result!!
            val colExists = doc.exists()

            metaReturnedListener.onMetaReturned(colExists)
        } else {
            Log.d(TAG, "get failed with ", task.exception)
        }
    }
}

第 3 步。 调用步骤 2 中定义的方法。传递您在步骤 1 中定义的对象。该对象将从步骤 2 中的方法调用,因此被覆盖的方法将接收值/对象作为参数,然后您可以将其分配给同类型的变量。你也可以传递其他不同类型的参数,但是你必须在第2步更新方法签名

fun saveModulesToFirestore(colName: String, saveCode: String) {

    var collectionExists = false

    if (saveCode == FirebaseHelper.ADD_TO_COLLECTION){
        nameExists(object: OnMetaReturnedListener{
            override fun onMetaReturned(colExists: Boolean) {
                collectionExists = colExists
                if (collectionExists){
                    val dialog = CollectionExistsDialogFragment.newInstance()
                    dialog.show(fragmentManager, DIALOG_COLLECTION_EXISTS)
                    return
                } else{
                    addNewCollectionToFirebase(colName)
                }
            }
        }, colName)
    }

}

【讨论】:

    猜你喜欢
    • 2019-03-29
    • 2020-11-28
    • 1970-01-01
    • 2021-03-26
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    相关资源
    最近更新 更多