Google Cloud FireStore 1 лимит в секунду для документа и как его обойти - PullRequest
0 голосов
/ 04 мая 2019

В этом видео https://youtu.be/o7d5Zeic63s?t=145 говорится, что для документа существует ограничение в 1 запись в секунду.

Если вы подаете заявку на просмотр и хотите сохранить количество отзывов для 5,4,3,2,1 звездных оценок для ресторанного документа, как бы вы сделали это для приложения с большим числомодновременных пользователей тогда?Подумайте о таком популярном приложении, как foursquare ... Я думаю, что в этом случае было бы невозможно сохранить количество оценок в самом документе ресторана, например:

Restaurant:
 - name
 - address
 - ratings
  - 1 start: count
  - 2 stars: count
  - 3 starts: count
  - 4 stars: count
  - 5 starts count

.чем 1 попытка обновления по количеству звезд подсчитывает для одного и того же ресторана, что вполне возможно в этом популярном приложении.

В этом случае я могу подумать о сохранении вложенной коллекции RATINGS и записи рейтингового документаза каждый рейтинг.Тогда я мог бы получить количество оценок для 4-звездочного обзора.Но когда я пытаюсь подсчитать количество документов с 4-звездным рейтингом, будет ли это похоже на 30-килобайтный биллинг, если есть 4-звездочный рейтинг 30 000?Как бы вы получили этот счет, не взимая плату за 30 тыс. Чтений?

Как вы могли бы избежать этого и как бы вы сохраняли / обновляли количество звездных рейтингов для ресторана?

Редактировать: я видел этот пост: Как подсчитать количество документов в коллекции с Cloud Firestore

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

1 Ответ

0 голосов
/ 04 мая 2019

Я думаю, что нашел решение и хочу поделиться им с вами.

Для решения этой проблемы мы можем использовать Распределенные счетчики , как описано здесь: 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;
    });
}
...