首页 > 解决方案 > 如何从 Firebase 获取符合两个条件的数据,其中一个条件是数组?

问题描述

我正在使用以下代码从FirestoreZip Codes 数组(从名为“users”的集合中检索)获取数据数组。然后,我想从另一个集合(称为“订单”)中获取与数组中的任何邮政编码匹配的数据,以及与待处理、打包、处理中的“订单状态”匹配的数据。

        fun getZipCodesFromFirebase(fragment: OrdersByStatusFragment) {

    val uid = FirebaseAuth.getInstance().currentUser!!.uid
    val rootRef = FirebaseFirestore.getInstance()
    val followingRef = rootRef.collection("users")
    val uidRef = followingRef.document(uid)
    uidRef.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val document = task.result
            if (document.exists()) {
                val zipCodes = document.toObject(User::class.java)?.zip_codes
                Log.d("Zip Codes", zipCodes.toString())
                
                getOrderStatusList(fragment, zipCodes)

            } else {
                Log.d("TAG", "No such document")
            }
        } else {
            Log.d("TAG", "get failed with ", task.exception)
        }
    }

}

然后,我尝试使用以下代码来获取具有上述订单状态的订单以及与任何邮政编码匹配的订单。但我无法正确理解。

    fun getOrderStatusList(fragment: OrdersByStatusFragment, zipList: List<String>?) {

    mFireStore.collection("orders")
        .whereEqualTo("address.zipCode", zipList?.get(0))
        .whereEqualTo("address.zipCode", zipList?.get(1))
        .whereEqualTo("address.zipCode", zipList?.get(2))
        .whereEqualTo("address.zipCode", zipList?.get(3))
        .whereEqualTo("address.zipCode", zipList?.get(4))
        .whereEqualTo("address.zipCode", zipList?.get(5))
        .whereEqualTo("address.zipCode", zipList?.get(6))
        .whereEqualTo("address.zipCode", zipList?.get(7))
        .whereEqualTo("address.zipCode", zipList?.get(8))
        .whereEqualTo("address.zipCode", zipList?.get(9))
        .get()
        .addOnSuccessListener { document ->
            val list: ArrayList<OrderStatus> = ArrayList()

            for (i in document.documents) {

                val orderStatus = i.toObject(OrderStatus::class.java)!!
                orderStatus.id = i.id

                if (orderStatus.order_status == "Pending" || orderStatus.order_status == "Packed" || orderStatus.order_status == "In Process"
                    || orderStatus.order_status == "Order Received") {
                    list.add(orderStatus)
                }

            }
            Log.d("Zip Code", list.toString())
            fragment.successOrderStatusList(list)

        }
        .addOnFailureListener {
            fragment.hideProgressDialog()
        }
}

简而言之,我想要与邮政编码和订单状态匹配的订单。其中 Zip codeusers从数组中调用的另一个集合中检索的,并且订单状态是硬编码的。

数据库结构可以在以下屏幕截图中看到。

带有字段“zip_codes”的集合“用户”。

在此处输入图像描述

包含字段“order_status”和“zip_codes”的集合“订单”

在此处输入图像描述

我希望我的问题足够清楚。

谢谢你。

编辑:>>最新的工作代码。

    fun getOrderStatusList(fragment: OrdersByStatusFragment, zipList: List<String>?) {

    mFireStore.collection("orders")
        .whereIn("address.zipCode", zipList!!)
        .get()
        .addOnSuccessListener { document ->
            val list: ArrayList<OrderStatus> = ArrayList()

            for (i in document.documents) {

                val orderStatus = i.toObject(OrderStatus::class.java)!!
                orderStatus.id = i.id

                if (orderStatus.order_status == "Pending" || orderStatus.order_status == "Packed" || orderStatus.order_status == "In Process"
                    || orderStatus.order_status == "Order Received"
                ) {
                    list.add(orderStatus)
                }

            }
            Log.d("Zip Code", list.toString())
            fragment.successOrderStatusList(list)

        }
        .addOnFailureListener {
            fragment.hideProgressDialog()
        }
}

标签: kotlingoogle-cloud-firestore

解决方案


这个构造:

mFireStore.collection("orders")
    .whereEqualTo("address.zipCode", zipList?.get(0))
    .whereEqualTo("address.zipCode", zipList?.get(1))
    .whereEqualTo("address.zipCode", zipList?.get(2))
    .whereEqualTo("address.zipCode", zipList?.get(3))
    .whereEqualTo("address.zipCode", zipList?.get(4))

过滤结果以仅包含zipCode顶级address字段的属性等于zipList?.get(0)、等于等于zipList?.get(1)zipList?.get(2)元素。由于没有单个字段可以等于多个值,因此不返回任何内容。

您更有可能正在寻找一个array-contains-anycondition,它看起来像这样:

citiesRef.whereArrayContainsAny("zipCode", zipList!)

与 filter on 类似order_status,您可以使用in同一文档中的条件:

citiesRef
  .whereIn("order_status", listOf("Pending", "Packed", "In Process"))

不幸的是,您不能将这两个条件结合起来,如文档所述:

每个查询最多可以使用一个in, not-in, orarray-contains-any子句。您不能在同一个查询中组合这些运算符。

因此,您必须在查询中执行其中一个条件,然后在应用程序代码中过滤另一个条件。


推荐阅读