Swift Firebase-最有效的方法来通过观察裁判获得所有评分的总和?

时间:2019-04-19 03:50:26

标签: ios swift firebase firebase-realtime-database

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

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 )。

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

是否有一种更有效的方法来获得所有评级的总和而无需使用太多代码?

在这种情况下,交易块会更好吗?根据我的理解,交易块会跟踪评分,因此即使用户用1.5 rating查看 restaurantId_0 ,如果另外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
                        }
                    }
                })

1 个答案:

答案 0 :(得分:0)

您第一次使用的基本方法看起来不错,所以我怀疑是否有一种更有效的方法,尽管您的代码看起来有些费解。

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)
    })

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