在 Firestore 中执行复合查询时出错

Posted

技术标签:

【中文标题】在 Firestore 中执行复合查询时出错【英文标题】:Error while performing compound queries in firestore 【发布时间】:2021-10-01 06:33:33 【问题描述】:

我想在 firestore 中执行复合查询,我想获取字段 bloodgroup 等于 A+ 且字段 createdBy 不等于 email 的所有文档。此电子邮件是登录用户的电子邮件。当我执行查询时,我得到 NullPointerException。如何正确执行查询 021-07-24 19:50:24.746 17550-17550/com.example.bloodbankcompany E/androidRuntime: FATAL EXCEPTION: main Process: com.example.bloodbankcompany, PID: 17550 java.lang.NullPointerExceptionatcom.example.bloodbankcompany.UserlistActivity$EventChangeListener3$1.onEvent(UserlistActivity.kt:217) 我将文档快照存储在userArrayList 数组中。如果没有 whereNotEqualTo 查询,我将获得输出,其中我的文档在 recyclerview 中列出。

private fun EventChangeListener2()

        val sharedPreferences1 = getSharedPreferences("email", Context.MODE_PRIVATE)
        val email: String? = sharedPreferences1.getString("email","null")?.trim()

        Toast.makeText(this, "s-s-rae$email", Toast.LENGTH_SHORT ).show()

        mFireStore.collection("applicationForm").whereNotEqualTo("createdBy",email).whereEqualTo("bloodgroup","A+").addSnapshotListener(object : EventListener<QuerySnapshot>
            override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) 
                if (error!= null)
                    Log.e("firestore error", error.message.toString())
                

                for(dc: DocumentChange in value?.documentChanges!!)
                    if (dc.type== DocumentChange.Type.ADDED)


                        userArrayList.add(dc.document.toObject(User1::class.java))
                        var number=userArrayList
                        var number1 =userArrayList

                    
//                    Toast.makeText(applicationContext,userArrayList.toString(), Toast.LENGTH_SHORT).show()

                
                myAdapter.notifyDataSetChanged()
            

        )

    

【问题讨论】:

【参考方案1】:

好吧,我已经编辑了你的一些代码,如果它仍然不起作用,请添加评论。

另外,下面评论了有关更改的说明。

private fun EventChangeListener2() 

        val sharedPreferences1 = getSharedPreferences("email", Context.MODE_PRIVATE)
        val email: String? = sharedPreferences1.getString("email", "null")?.trim()

        Log.d("firestore email", email.toString())

        Toast.makeText(this, "s-s-rae$email", Toast.LENGTH_SHORT).show()

        // try and catch will avoid your app to crash.
        try 

            //ref
            var ref = mFireStore.collection("applicationForm")
                .whereEqualTo("bloodgroup", "A+")


            /**
             *  I believe since your email is of type nullable and there may be
             *  maybe a chance that email is null and is given to whereNotEqualTo
             *  I am just making an assumption here since I don't know what you
             *  recieve from sharedPreferences and whether it is null or not
             *
             *  So, what I have done here is,
             *  firstly, I have split the firestore call into 2 parts and
             *  Secondly, I have a null-check for email, if it is
             *  not-null ref will also include this query
             *
             */
            //null Check for email
            if (email != null) ref = ref.whereNotEqualTo("createdBy", email)

            // Snapshot Listener
            ref.addSnapshotListener(object : EventListener<QuerySnapshot> 
                override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) 
                    if (error != null) 
                        Log.e("firestore error", error.message.toString())
                    

                    for (dc: DocumentChange in value?.documentChanges!!) 
                        if (dc.type == DocumentChange.Type.ADDED) 


                            userArrayList.add(dc.document.toObject(User1::class.java))
                            var number = userArrayList
                            var number1 = userArrayList

                        
//                    Toast.makeText(applicationContext,userArrayList.toString(), Toast.LENGTH_SHORT).show()

                    
                    myAdapter.notifyDataSetChanged()
                

            )
         catch (e: Exception) 
            Log.e("firestore error", "Error", e)
        
    

编辑: 根据 firebase 文档,

https://firebase.google.com/docs/firestore/query-data/indexing#exemptions

如果您尝试使用未映射到现有索引的范围子句进行复合查询,则会收到错误消息。错误消息包含在 Firebase 控制台中创建缺失索引的直接链接。

【讨论】:

当我单独使用查询 whereEqualTo 和单独使用 whereNotEqualTo 时,我得到了输出。但是当我将两个查询放在一起 .whereEqualTo.whereNotEqualTo 时,我得到了错误。 你能不能用这个替换你的代码并在它失败之前发送 logcat 值。 所以这里发生了什么,即上面在答案中提供的代码是,如果电子邮件不为空,它将结合whereEqualTowhereNotEqualTo 否则只有whereEqualTo 会运行 2021-07-24 23:01:45.770 14803-14803/com.example.bloodbankcompany E/firestore error: FAILED_PRECONDITION: The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/fir-2company/firestore/indexes?create_composite= 2021-07-24 23:01:45.771 14803-14803/com.example.bloodbankcompany E/AndroidRuntime: FATAL EXCEPTION: PID: 14803 java.lang.NullPointerException 所以在您的错误复制中生成了一个链接并将其粘贴“https:// .......... 8QAQ”

以上是关于在 Firestore 中执行复合查询时出错的主要内容,如果未能解决你的问题,请参考以下文章

使用 Firestore 限制项目时出错

isEqual to operator 在 Flutter Firestore 中无法正常工作

在颤动中使用 REST api 将列表数据发送到云 Firestore 时出错

在 iOS 中安装 Firestore 时出错?

在 Jest 中模拟 Firebase 管理员时出错:“TypeError:admin.firestore 不是函数”

从 StreamBuilder BloC firestore Flutter 获取数据时出错