如何检查Firestore文档指定字段等于某值 实现商品名重复校验
实现方案说明
注意:Firestore查询属于异步IO操作,原有同步返回Boolean的方法结构无法直接适配,以下提供两种常用的Kotlin实现方案,无需手动遍历全量文档,直接使用Firestore条件查询whereEqualTo在服务端过滤匹配结果,性能更高、更省流量。
方案1:协程实现(安卓官方推荐)
需要先引入协程相关依赖(已有可忽略):
// 模块级build.gradle添加 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3"
改造后的校验方法代码:
private suspend fun validateProduct() : Boolean{ val newProductName = binding.etNewProductName.text.toString().trim() val newProductPrice = binding.etNewProductPrice.text.toString().trim() val newProductCategory = binding.spNewProductCategory.selectedItem.toString() // 原有同步校验逻辑 when{ TextUtils.isEmpty(newProductName) -> { showErrorSnackBar(binding.root, "Product name cannot be empty.", true) return false } TextUtils.isEmpty(newProductPrice) -> { showErrorSnackBar(binding.root, "Price cannot be empty.", true) return false } newProductCategory == binding.spNewProductCategory.getItemAtPosition(0) -> { showErrorSnackBar(binding.root, "Please select a valid category.", true) return false } } // Firestore商品名重复校验 val productsRef = FirebaseFirestore.getInstance().collection("替换为你的商品集合名") return try { // 直接查询name字段等于当前输入商品名的文档 val querySnapshot = productsRef.whereEqualTo("name", newProductName).get().await() if (!querySnapshot.isEmpty) { showErrorSnackBar(binding.root, "该商品名称已存在,请更换后重试", true) false } else { true } } catch (e: Exception) { showErrorSnackBar(binding.root, "校验商品信息失败,请检查网络后重试", true) false } }
调用方式(需要在协程作用域中执行):
// 示例:提交按钮点击事件中调用 binding.btnSubmitProduct.setOnClickListener { lifecycleScope.launch { val isValidatePass = validateProduct() if (isValidatePass) { // 校验通过,执行后续商品提交逻辑 } } }
方案2:回调实现(无需协程)
如果项目未引入协程,可以用回调方式处理异步结果:
private fun validateProduct(onValidateResult: (Boolean) -> Unit) { val newProductName = binding.etNewProductName.text.toString().trim() val newProductPrice = binding.etNewProductPrice.text.toString().trim() val newProductCategory = binding.spNewProductCategory.selectedItem.toString() // 原有同步校验逻辑 when{ TextUtils.isEmpty(newProductName) -> { showErrorSnackBar(binding.root, "Product name cannot be empty.", true) onValidateResult(false) return } TextUtils.isEmpty(newProductPrice) -> { showErrorSnackBar(binding.root, "Price cannot be empty.", true) onValidateResult(false) return } newProductCategory == binding.spNewProductCategory.getItemAtPosition(0) -> { showErrorSnackBar(binding.root, "Please select a valid category.", true) onValidateResult(false) return } } // Firestore商品名重复校验 val productsRef = FirebaseFirestore.getInstance().collection("替换为你的商品集合名") productsRef.whereEqualTo("name", newProductName).get() .addOnSuccessListener { querySnapshot -> if (!querySnapshot.isEmpty) { showErrorSnackBar(binding.root, "该商品名称已存在,请更换后重试", true) onValidateResult(false) } else { onValidateResult(true) } } .addOnFailureListener { showErrorSnackBar(binding.root, "校验商品信息失败,请检查网络后重试", true) onValidateResult(false) } }
调用方式:
binding.btnSubmitProduct.setOnClickListener { validateProduct { isValidatePass -> if (isValidatePass) { // 校验通过,执行后续商品提交逻辑 } } }
额外优化建议
如果需要彻底避免商品名重复,建议在Firestore安全规则中添加同名限制,或者直接用商品名作为文档ID,从服务端层面规避重复写入的问题。
内容的提问来源于stack exchange,提问作者Jay Garzon
相关产品推荐
相关产品推荐

