#javascript #node.js #firebase #google-cloud-firestore #google-cloud-functions
#javascript #node.js #firebase #google-cloud-firestore #google-cloud-функции
Вопрос:
У меня есть облачная функция, в которой я реализую рейтинг пользователей. Я использую транзакцию, чтобы проверить, оценивал ли пользователь ранее, и если нет, я создаю новый документ, в котором есть только одно поле — userId. В следующий раз, когда пользователь попытается оценить тот же ресторан, я вообще не буду обновлять среднюю оценку. Итак, как я могу просто обновить рейтинг для пользователя, который уже получил рейтинг? Ниже вы можете увидеть, как я реализую рейтинг (если пользователь оценивает ресторан в первый раз):
...
.then(async function (doc) {
if (doc.empty) {
let add_clients_rating = admin.firestore().collection("restaurants_collection").doc(vendor_id).collection('ratings').doc();
let restaurants_collection = admin.firestore().collection("restaurants_collection").doc(vendor_id);
await admin.firestore().runTransaction(async (transaction) => {
const restDoc = await transaction.get(restaurants_collection);
// Compute new number of ratings
const newNumRatings = restDoc.data().noRat 1;
// Compute new average rating
const oldRatingTotal = restDoc.data().rat * restDoc.data().noRat;
const newAvgRating = (oldRatingTotal ratingVal) / newNumRatings;
const round_no_rating = Math.round(newAvgRating);
// create new document with user id
transaction.set(add_clients_rating, {
uID: userId
});
// Update restaurant info
transaction.update(restaurants_collection, {
rat: round_no_rating,
noRat: newNumRatings
});
Это то, что я пытался реализовать для обновления рейтинга пользователя:
let restaurants_collection =
admin.firestore().collection("restaurants_collection").doc(vendor_id);
await admin.firestore().runTransaction(async (transaction) => {
const restDoc = await transaction.get(restaurants_collection);
// Compute new number of ratings
const newNumRatings = restDoc.data().noRat;
// Compute new average rating
const oldRatingTotal = restDoc.data().rat * restDoc.data().noRat;
const newAvgRating = (oldRatingTotal ratingVal) / newNumRatings;
const round_no_rating = Math.round(newAvgRating);
// Update restaurant info
transaction.update(restaurants_collection, {
rat: round_no_rating
});
То, что я изменил здесь, это const newNumRatings = restDoc.data().noRat;
эта строка, в частности, я удалил 1
. Но проблема в том, что он продолжает добавлять новое значение к среднему рейтингу. Итак, если пользователь1 уже получил рейтинг раньше, когда он попытался обновить этот рейтинг, он добавляет новое значение. Если среднее значение равно 3, а значение скорости пользователя 1 равно 5, это соответствует старому среднему значению (понятия не имею, как оно его вычисляет), а затем, когда пользователь1 снова обновляется, средняя скорость становится все больше и больше 9, 10, 11, …
Комментарии:
1. Я неясен. Не могли бы вы отредактировать вопрос, чтобы более подробно объяснить, что на самом деле делает этот код, который отличается от того, что вы хотите? Что с этим не так?
2. @DougStevenson приведенный выше код отлично работает для ПЕРВОГО рейтинга. Однако, как я могу обновить рейтинг пользователя, который уже оценил тот же ресторан ранее?!
3. Что произойдет, когда вы запустите его во второй раз? Пожалуйста, будьте конкретны. Есть ли ошибка? Делает ли это что-то отличное от того, что вы ожидаете?
4. @DougStevenson ничего, очевидно, я ничего не делаю для обновления рейтинга пользователя, который уже обновился. Я просто не знаю, как это сделать!
5. Итак, как только они устанавливают рейтинг, это теряется?… если это так, было бы сложно реализовать это… моя идея состояла в том, чтобы взять старое значение и создать метод специально для обновления среднего значения: вы получаете новую ставку, вычитаете старую ставку из общей суммы и добавляете новую, и вы продолжаете как обычно вычислять среднее значение с общей суммой ставок… без старого значения… вы не сможете вычислить новую сумму всех ставок, так как в конечном итоге она просто сложится (и приведет к ошибке, которая у вас есть), поэтому вам понадобится старое значение.