Swift Firebase -Самый эффективный способ получить общую сумму всех рейтингов от наблюдения реф? - PullRequest
0 голосов
/ 19 апреля 2019

Моя структура базы данных выглядит следующим образом:

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

Я могу получить эту информацию двумя различными способами, используя приведенные ниже методы. В обоих случаях мне нужно просмотреть все отзывы, чтобы получить сумму всех оценок. Как вы можете видеть ниже, для получения суммы требуется много кода.

Есть ли более эффективный способ получить сумму всех оценок без использования такого большого количества кода?

Будет ли блок транзакций работать лучше в этой ситуации? Насколько я понимаю, блок транзакций будет отслеживать рейтинги, поэтому, даже если пользователь просматривает restaurantId_0 с 1.5 rating, если 3 других пользователя оставили высокий рейтинг, блок транзакции немедленно отразит это, и звезда рейтинг изменится (после запуска новых расчетов)

1-й способ

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

2-й способ

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 голосов
/ 19 апреля 2019

Базовый подход вашего первого выглядит хорошо, поэтому я сомневаюсь, что есть более эффективный способ, хотя ваш код выглядит немного запутанным.

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

Ваш второй подход может работать, но не является идиоматическим, поскольку вы вкладываете второго прослушивателя в те же данные, которые уже загрузили.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...