如何继续向现有 Firestore 查询添加条件?

Posted

技术标签:

【中文标题】如何继续向现有 Firestore 查询添加条件?【英文标题】:How to keep adding conditions to an existing Firestore query? 【发布时间】:2021-07-29 21:56:48 【问题描述】:

在没有应用任何过滤器的情况下,我正在像这样查询我的 Firestore 数据库:

var query:Query = db.collection("myFirestoreData")

queryData()

我的应用还有 4 个用于过滤的按钮。

例如,如果点击“便宜”,这就是我过滤 isCheap = true 的数据的方式:

if cheapOnly == true 
             query = query
                .whereField("isCheap", isEqualTo: true)
        

如果有人点按“简单”,我该如何应用两个过滤器(即过滤isCheap = trueisEasy = true的数据?我想我可以像这样在query 引用中添加另一个whereField 条件:

if cheapOnly == true 
             query = query
                .whereField("isCheap", isEqualTo: true)
        
if easyOnly == true 
             query = query
                .whereField("isEasy", isEqualTo: true)
        

当两个按钮都被点击时,上面的所有代码都会运行,但我继续只获得一个或另一个过滤。我该怎么做:

    在另一个之上应用查询条件(即,通过 简单和便宜的过滤条件)?以及 过滤器的点击顺序是否无关紧要(即,无论是先点击还是第二点击 Easy 或 Cheap,结果都相同)?

非常感谢任何支持/指导!

编辑:

在下面添加了我的数据模型的完整代码,看看是否有人可以在那里发现不正确的地方。

class MealPlanModel 
    
    var delegate:MealPlanProtocol?
    var listener:ListenerRegistration?
    var mealPlan = [MealPlan]()
    
    func getMealPlans(starred starredOnly:Bool = false, textToQuery searchText:String = "", easyFiltered easyOnly:Bool = false,  cheapFiltered cheapOnly:Bool = false, highProteinFiltered highProteinOnly:Bool = false, vegetarianFiltered vegetarianOnly:Bool = false) 

        // Detach any listener
        listener?.remove()
        
        // Get a reference to the database
        let db = Firestore.firestore()
        
        var query:Query = db.collection("mealPlans")
        
        if cheapOnly == true 
             query = query
                .whereField("isCheap", isEqualTo: true)
        
        
        if easyOnly == true 
             query = query
                .whereField("isEasy", isEqualTo: true)
        

        func queryData() 
            
            self.listener = query.addSnapshotListener( (snapshot, error) in
                
                // Check for errors
                if error == nil && snapshot != nil 
                    
                    var mealPlans = [MealPlan]()
                    
                    // Parse documents into mealPlans
                    for doc in snapshot!.documents 
                        
                        let m = MealPlan(
                            docID: doc["docID"] as? String,
                            title: doc["title"] as? String)
                        
                        mealPlans.append(m)
                    
                    DispatchQueue.main.async 
                        self.delegate?.mealPlansRetrieved(mealPlans: mealPlans)
                    
                
            )
        
        
        queryData()
        
    

【问题讨论】:

您在问题中分享的代码乍一看还不错。如果您可以显示一个重现问题的 sn-p,可能会更容易提供帮助。 谢谢@FrankvanPuffelen!我在我的数据模型中添加了其余代码。你发现那里有什么不正确的地方吗?我想知道我是否可能在错误的地方调用queryData(),因此查询在我的if 语句之间重置。 你能在queryData函数中打印running query data with isEasy and isCheap吗?所以我们知道函数正在运行并且 isEasy 和 isCheap 的值都是 true? 【参考方案1】:

那么,根据我的理解,您希望允许多个真实条件,仅在选中时?我做了一些非常相似的事情,很有趣,一个像你这样的食物应用程序。这只是关于“操纵”对数据库的引用,如下所示:

var ref = db.collection("myFirestoreData")
    if cheapOnly 
       ref = ref.whereField("isCheap", isEqualTo: true)
            
    if easyOnly 
        ref = ref.whereField("isEasy", isEqualTo: true)
       

  ref.limit(to: 20).getDocuments 
        //Get your documents
    

这是基于您传递选项值的假设,即便宜、简单等。

【讨论】:

非常感谢这个例子!在我看来,我的结构与您的结构相似。我在我的数据模型中发布了其余的相关代码。你觉得里面有什么不对吗?是不是我打错了queryData() @amirbt17 你为什么要使用监听器?侦听器实际上应该只用于来自 Firebase 的更新,使用侦听器可能会变得非常昂贵。您只是想获取您的参考,查询您认为合适的方式并使用.getDocuments。在您的 getDocuments 闭包中,您可以转换数据等。【参考方案2】:

以下工作:

if easyOnly == true || cheapOnly == true || highProteinOnly == true || vegetarianOnly == true 
            
            // Reset the query
            db.collection("mealPlans").document().getDocument  (snapshot, error) in
                
                self.query = db.collection("mealPlans")
                
                // Refine the query based on the button taps
                if easyOnly == true 
                    self.query = self.query
                    .whereField("isEasy", isEqualTo: true)
                
                
                if cheapOnly == true 
                    self.query = self.query
                    .whereField("isCheap", isEqualTo: true)
                
                
                if highProteinOnly == true 
                    self.query = self.query
                    .whereField("isHighProtein", isEqualTo: true)
                
                
                if vegetarianOnly == true 
                    self.query = self.query
                    .whereField("isVegetarian", isEqualTo: true)
                

                queryData()
             
         else 
            db.collection("mealPlans").document().getDocument  (snapshot, error) in
                
                self.query = db.collection("mealPlans")
             
                queryData()
             
        

self.query = db.collection("mealPlans") 在按下多个按钮时帮助重置查询。

queryData()在每个查询结束时实现,以便在设置所有.whereField参数后提交查询。

【讨论】:

以上是关于如何继续向现有 Firestore 查询添加条件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 firestore 中的现有数组中添加或删除项目?

颤振 |如何将数据添加到 Firestore 中的现有文档

Flutter Firestore 复合查询

带条件的 Prisma 查询

如何使用 Firestore 运行地理“附近”查询?

如何向云 Firestore 中的对象添加新属性 [重复]