Моя структура базы данных выглядит следующим образом:
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
}
}
})