I have a food app with a star system. Every time a user selects a rating/star I send their rating to the database and then run a firebase transaction
to update the total amount of users who left a rating.
let theirRating: Double = // whatEverStarRatingTheySelected let dict = [currentUserId: theirRating] let reviewsRef = Database.database().reference().child("reviews").child(postId) reviewsRef.updateChildValues(dict) { (error, ref) in let postsRef = Database.database().reference().child("posts").child(postId).child("totalUsersCount") postsRef.runTransactionBlock({ (mutableData: MutableData) -> TransactionResult in // ... }) }
When displaying the actual rating I pull the the post which has the totalUsersCount as a property, I pull all of the users actual ratings, add them all together, and then feed both numbers into an algo to spit out the actual rating. I do all of this on the client. How can I do the same thing "I pull all of the users actual rating, add them all together" with a Cloud Function, that is similar to this answer?
Database.database().reference().child("posts").child(postId).observeSingleEvent(of: .value, with: { (snapshot) in guard let dict = snapshot.value as? [String:Any] else { return } let post = Post(dict: dict) let totalUsers = post.totalUsersCount Database.database().reference().child("reviews").child(postId).observeSingleEvent(of: .value, with: { (snapshot) in var ratingSum = 0.0 // *** how can I do this part using a Cloud Function so that way I can just read this number as a property on the post instead of doing all of this on the client *** for review in (snapshot.children.allObjects as! [DataSnapshot]) { guard let rating = review.value as? Double else { continue } ratingSum += rating } let starRatingToDisplay = self.algoToComputeStarRating(totalUsersCount: totalUsersCount, ratingsSum: ratingSum) }) })
This isn't a question about the algoToComputeStarRating, that I can do on the client. I want to add all of the user's ratings together using a Cloud Function, then just add that result as a property to the post. That way when I pull the post all I have to do is:
Database.database().reference().child("posts").child(postId).observeSingleEvent(of: .value, with: { (snapshot) in guard let dict = snapshot.value as? [String:Any] else { return } let post = Post(dict: dict) let totalUsersCount = post.totalUsersCount let ratingsSum = post.ratingsSum let starRatingToDisplay = self.algoToComputeStarRating(totalUsersCount: totalUsersCount, ratingsSum: ratingSum) })
Database structure:
@posts @postId -postId: "..." -userId: "..." -totalUsersCount: 22 -ratingsSum: 75 // this should be the result from the cloud function @reviews @postId -uid_1: theirRating -uid_2: theirRating // ... -uid_22: theirRating
This is what I tried so far:
exports.calculateTotalRating = functions.https.onRequest((data, response) => { const postId = data.postId; const totalUsersCtRef = admin.database().ref('/posts/' + postId + '/' + 'totalUsersCt'); const postsRef = admin.database().ref('/posts/' + postId); admin.database().ref('reviews').child(postId).once('value', snapshot => { if (snapshot.exists()) { var ratingsSum = 0.0; snapshot.forEach(function(child) { ratingsSum += child().val() }) .then(() => { return postsRef.set({ "ratingsSum": ratingsSum}) }) .then(() => { return totalUsersCtRef.set(admin.database.ServerValue.increment(1)); }) .catch((error) => { console.log('ERROR - calculateTotalRating() Failed: ', error); }); } }); });
https://stackoverflow.com/questions/66010766/firebase-how-to-run-a-calculation-using-a-cloud-function February 02, 2021 at 09:32PM
没有评论:
发表评论