如何在Swift中实现可动态添加过滤条件的Firestore查询?
解决方案
Firestore Swift SDK中的Query为不可变结构体,每次调用whereField、order、limit等条件拼接方法都会生成全新的Query实例,只要将新实例赋值回原有变量即可实现动态拼接查询条件的需求,你的整体逻辑完全正确,仅存在两处细节错误导致逻辑不生效:
- 排序和条数限制的方法返回的新Query没有赋值回原变量,修改不生效
- 代码中存在两处笔误,错误将
self.lbl_field.text、self.lbl_duration.text写为了cell.lbl_field.text、cell.lbl_duration.text,导致条件取值错误
修复后可运行的完整代码
var query = db.collection("admissions") // 搜索关键词条件 if (self.txt_search.text?.count ?? 0 > 0) { query = query.whereField("keyword", arrayContains: self.txt_search.text ?? "") } // 州/省筛选条件 if(self.lbl_state.text != "State" && self.lbl_state.text != "" && self.lbl_state.text != "Any") { query = query.whereField("state", isEqualTo: self.lbl_state.text ?? "") } // 学历等级筛选条件 if(self.lbl_level.text != "Level" && self.lbl_level.text != "" && self.lbl_level.text != "Any") { query = query.whereField("type", isEqualTo: self.lbl_level.text ?? "") } // 专业领域筛选条件 if(self.lbl_field.text != "Field" && self.lbl_field.text != "" && self.lbl_field.text != "Any") { // 修复笔误:从self取值而非cell query = query.whereField("field_broad", isEqualTo: self.lbl_field.text ?? "") } // 院校筛选条件 if(self.lbl_provider.text != "Provider" && self.lbl_provider.text != "" && !self.selectedUniversity.contains("Any")) { query = query.whereField("university", in: self.selectedUniversity) } // 学制筛选条件 if(self.lbl_duration.text != "Duration" && self.lbl_duration.text != "" && self.lbl_duration.text != "Any") { // 修复笔误:从self取值而非cell if(self.lbl_duration.text == "<1 year") { query = query.whereField("duration", isLessThanOrEqualTo: 365) } else if(self.lbl_duration.text == "1-2 year") { query = query.whereField("duration", isGreaterThanOrEqualTo: 365).whereField("duration", isLessThanOrEqualTo: 365 * 2) } else { query = query.whereField("duration", isGreaterThanOrEqualTo: 365 * 2) } } // 修复:排序和分页结果赋值回query query = query.order(by: "duration").order(by: "id").limit(to: 50) // 执行查询 query.getDocuments() { (querySnapshot, err) in AFWrapper.stopAnimating() if let err = err { print("Error getting documents: \(err)") } else { for document in querySnapshot!.documents { print("\(document.documentID) => \(document.data())") } } }
优化建议
可以把重复的参数合法性判断抽成单独的工具方法,减少冗余代码,示例如下:
func isValidFilterParam(_ value: String?, placeholder: String) -> Bool { guard let value = value, !value.isEmpty else { return false } return value != placeholder && value != "Any" } // 调用示例 if isValidFilterParam(self.lbl_state.text, placeholder: "State") { query = query.whereField("state", isEqualTo: self.lbl_state.text ?? "") }
内容的提问来源于stack exchange,提问作者Guri
相关产品推荐
相关产品推荐

