Я думаю, что нашел решение и хочу поделиться им с вами.
Для решения этой проблемы мы можем использовать Распределенные счетчики , как описано здесь: https://firebase.google.com/docs/firestore/solutions/counters
Пропускная способность записи увеличивается линейно с количеством шардов,таким образом, распределенный счетчик с 10 осколками может обрабатывать в 10 раз больше записей, чем традиционный счетчик.
Подводя итог, вы создаете осколки для каждой звездной оценки.Например, мы могли бы создать 10 осколков для каждого звёздного рейтинга (всего 50 осколков), затем мы можем получить счет для рейтинга 4 звезд, суммируя значения внутри этих 10 осколков рейтинга 4 звезд.
Сохранить вПримите во внимание эти ограничения:
Количество осколков - Количество осколков контролирует производительность распределенного счетчика.При слишком малом количестве шардов некоторые транзакции, возможно, придется повторить перед выполнением, что замедлит запись.При слишком большом количестве шардов чтение становится медленнее и дороже.
Стоимость - Стоимость считывания значения счетчика увеличивается линейно с количеством шардов, поскольку должна быть загружена вся подборка шардов.
Ниже приведен пример кода из документации пожарного депо, которую я связал выше.
Инициализация распределенного счетчика:
function createCounter(ref, num_shards) {
var batch = db.batch();
// Initialize the counter document
batch.set(ref, { num_shards: num_shards });
// Initialize each shard with count=0
for (let i = 0; i < num_shards; i++) {
let shardRef = ref.collection('shards').doc(i.toString());
batch.set(shardRef, { count: 0 });
}
// Commit the write batch
return batch.commit();
}
Выберитеслучайный осколок и увеличение количества:
function incrementCounter(db, ref, num_shards) {
// Select a shard of the counter at random
const shard_id = Math.floor(Math.random() * num_shards).toString();
const shard_ref = ref.collection('shards').doc(shard_id);
// Update count
return shard_ref.update("count", firebase.firestore.FieldValue.increment(1));
}
Запрос всех осколков и суммирование их полей:
function getCount(ref) {
// Sum the count of each shard in the subcollection
return ref.collection('shards').get().then(snapshot => {
let total_count = 0;
snapshot.forEach(doc => {
total_count += doc.data().count;
});
return total_count;
});
}