【问题标题】:How to Implement User-Specific Favourites using Firestore?如何使用 Firestore 实现用户特定的收藏夹?
【发布时间】:2021-06-05 07:47:04
【问题描述】:

我的项目包含一系列膳食计划。现在,用户可以star MealPlan,这将更新 MealPlan 文档中的 isStarred Bool 值。但是,这只会更新每个用户当前访问的数据库。

我如何对其进行编码,以便用户拥有自己的一套已加星标膳食计划?

我目前正在使用 Firebase 身份验证和 Firestore。这是我的 MealPlan 结构:

struct MealPlan {
    
    var docID:String?
    var title:String?
    var recipeSource:String?
    var estimatedTime:String?
    var coverImageView:String?
    var equipment:[String]?
    var instructions:[String]?
    var isStarred:Bool?
    
}

我的用户结构:

struct User {
    
    var userId:String?
    var firstName:String?
    var lastName:String?
    var email:String?
    
}

我的数据模型:

class MealPlanModel {
    
    var delegate:MealPlanProtocol?
    var listener:ListenerRegistration?
    
    func getMealPlans(_ starredOnly:Bool = false) {
        
        // Detach any listener
        listener?.remove()
        
        // Get a reference to the database
        let db = Firestore.firestore()
        
        var query:Query = db.collection("mealPlans")
        
        // If filtering for starred Meal Plans, update the query
        if starredOnly {
            query = query.whereField("isStarred", isEqualTo: true)
        }
        
        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,
                        recipeSource: doc["recipeSource"] as? String,
                        estimatedTime: doc["estimatedTime"] as? String,
                        coverImageView: doc["coverImageView"] as? String,
                        ingredientsProduce: doc["ingredientsProduce"] as? [String],
                        ingredientsProtein: doc["ingredientsProtein"] as? [String],
                        ingredientsSpices: doc["ingredientsSpices"] as? [String],
                        ingredientsOther: doc["ingredientsOther"] as? [String],
                        equipment: doc["equipment"] as? [String], instructions: doc["instructions"] as? [String],
                        isStarred: doc["isStarred"] as? Bool)
                    
                    mealPlans.append(m)
                    
                }
                
                // Call the delegate and pass back the notes in the main thread
                DispatchQueue.main.async {
                    self.delegate?.mealPlansRetrieved(mealPlans: mealPlans)
                }
                
                
            }
            
        })
        
    }
    
    func updateStarredStatus(_ docId:String, _ isStarred:Bool) {
        
        let db = Firestore.firestore()
        
        db.collection("mealPlans").document(docId).updateData(["isStarred":isStarred])
        
    }
    
}

以及在我的 View Controller 中主演的方法:

@IBAction func starButtonTapped(_ sender: Any) {
        
        // Toggle the star filter status
        isStarFiltered.toggle()
        
        // Run the query
        if isStarFiltered {
            model.getMealPlans(true)
        }
        else {
            model.getMealPlans()
        }
        
        // Update the starButton
        setStarFilterButton()
        
    }

是否需要将已加星标的 MealPlan 的 docID 复制到 Users 结构中的键中?然后在过滤星标 MealPlans 时显示那些 MealPlans?

非常感谢任何帮助/指导!

【问题讨论】:

    标签: ios database firebase google-cloud-firestore user-controls


    【解决方案1】:

    解决方案是让每个用户跟踪自己的膳食计划。您可以创建一个集合,在用户文档中存储膳食计划 ID,使其看起来像这样

    meals
       meal_0 //auto generated documentId
         //meal ingredients
       meal_1
         //meal ingredients
       meal_2
         //meal ingredients
    

    然后

    users
       user_0 //the documentId is the users uid
         //user info
         my_meals (collection)
            meal_0: true
            mean_2: true
    

    话虽如此,将数据保持在高水平以减少读取量并简化查询通常是个好主意,因此这种结构可能会更好,而不是将用户餐点存储在用户文档中

    starred_meals
       user_0 //the documentId is the users uid
         meal_0: true
         mean_2: true
    

    当用户登录时,从 starred_meals 集合中读取他们的文档。

    稍微扩展一下,有时用户会希望在用餐时存储其他信息,而不是上面,这个怎么样

    starred_meals
       user_0
         starred_meal_0 (auto generated documentId)
            meal_id: meal_0
            wine_pairing: "Cabernet Sauvignon"
         starred_meal_1
            meal_id: meal_2
            wine_pairing: "Barolo"
    

    这样您就可以为每个用户存储与每餐相关的各种其他信息

    【讨论】:

    • 非常感谢您的解释 - 我认为现在对我来说很有意义。这听起来正确吗? 1. 将收藏的 mealPlan 文档复制到 userFavourites 集合中的用户文档 2. 过滤收藏的 mealPlans 时,请参考该文档以索引/显示主集合中的 mealPlans
    猜你喜欢
    • 2019-01-12
    • 2021-05-28
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 2023-02-02
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    相关资源
    最近更新 更多