【问题标题】:Swift Firebase -Most efficient way to get the total sum of all ratings from observing a ref?Swift Firebase - 通过观察 ref 获得所有评分总和的最有效方法?
【发布时间】:2019-04-19 03:50:26
【问题描述】:

我的数据库结构是这样的:

Restaurants
   @-restaurantId_0
      @-reviewId_1
          -rating: 1
          -user: uid_A
      @-reviewId_2
          -rating: 0.5
          -user: uid_B
      @-reviewId_3
          -rating: 3
          -user: uid_C
   @-restaurantId_1
      @-reviewId_4
          -rating: 4
          -user: uid_A
      @-reviewId_5
          -rating: 2.5
          -user: uid_S
   @-restaurantId_2
      // ...
   @-restaurantId_3
      // ...

我有一个星级评分系统,每个用户都可以为餐厅评分。我记录了他们在该评论下留下的评分和他们的 uid。

当显示特定餐厅及其星级时,我需要从每条评论中获取所有评分(针对该餐厅),然后进行一些计算以确定餐厅的总评分:

allTheRatingsAddedUp / totatNumOfReviews

例如。在我上面的数据库结构中,带有 restaurantId_0 的餐厅有 3 条评论,所有评分加起来为 4.5,所以它会有 1.5星级 总评分(4.5 / 3)。

我可以使用以下方法以 2 种不同的方式获取此信息。在这两种方式中,我都必须遍历所有评论以获得所有评分的总和。正如您在下面看到的,要获得总和涉及很多代码。

有没有更有效的方法可以在不使用这么多代码的情况下实现所有评分的总和?

在这种情况下,事务块会更好地工作吗?据我了解,交易块会跟踪评分,因此即使用户正在查看 restaurantId_01.5 rating,如果其他 3 个用户留下高评分,交易块也会立即反映这一点,并且星级会改变(运行新计算后)

第一种方式

Database.database().reference()
        .child("Restaurants")
        .child("restaurantId_0")
        .observeSingleEvent(of: .value, with: { (snapshot) in

            if !snapshot.exists() {
                return
            }

            let totatNumOfReviews = snapshot.childrenCount

            var arrOfReviews = [ReviewModel]()

            var allTheRatingsAddedUp = 0.0

            guard let dictionaries = snapshot.value as? [String: Any] else { return }

            var count = 0

            dictionaries.forEach({ (key, value) in

                guard let dict = value as? [String: Any] else { return }

                var review = ReviewModel(dict: dict)
                review.reviewId = key

                let isContained = arrOfReviews.contains(where: { (containedReview) -> Bool in
                    return review.reviewId == containedReview.reviewId
                })
                if !isContained {

                    arrOfReviews.append(review)

                    allTheRatingsAddedUp += review.rating ?? 0

                    count += 1

                    if count == totatNumOfReviews {

                        // run calculations on: allTheRatingsAddedUp / totatNumOfReviews
                    }
                }
            })
        })

第二种方式

Database.database().reference()
        .child("Restaurants")
        .child("restaurantId_0")
        .observeSingleEvent(of: .value) { (snapshot) in

            if !snapshot.exists() {
                return
            }

            let totatNumOfReviews = snapshot.childrenCount

            var arrOfReviews = [ReviewModel]()

            var allTheRatingsAddedUp = 0.0

            Database.database().reference()
                .child("Restaurants")
                .child("restaurantId_0")
                .observe( .childAdded, with: { (snapshot) in

                    if let dict = snapshot.value as? [String: Any] {

                        let review = ReviewModel(dict: dict)

                        arrOfReviews.append(review)

                        allTheRatingsAddedUp += review.rating ?? 0

                        if arrOfReviews.count == totatNumOfReviews {

                            // run calculations on: allTheRatingsAddedUp / totatNumOfReviews
                        }
                    }
                })

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    您的第一个基本方法看起来不错,所以我怀疑是否有更有效的方法,尽管您的代码看起来有点复杂。

    Database.database().reference()
        .child("Restaurants")
        .child("restaurantId_0")
        .observeSingleEvent(of: .value, with: { (snapshot) in
            let reviewCount = snapshot.childrenCount
            var ratingSum = 0.0
            for review in snapshot.children.allObjects as? [DataSnapshot] {
                guard let dict = review.value as? [String: Any]
                ratingSum = ratingSum + dict.rating ?? 0
            }
            print(ratingSum / reviewCount)
        })
    

    您的第二种方法可能有效,但不是惯用的,因为您在已加载的相同数据上嵌套了第二个侦听器。

    【讨论】:

    • 这是我正在寻找的确切答案。非常干净简洁。非常感谢!
    • 我还有一个关于在牢房中观察的问题要问。我将使用您刚刚添加的代码 sn-p。明天我可能会发布它。再次感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 2011-08-14
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 2017-12-02
    • 1970-01-01
    相关资源
    最近更新 更多