Как эффективно удалить старые облачные документы Firebase с помощью функции Google Cloud?

# #javascript #node.js #google-cloud-firestore #google-cloud-functions

Вопрос:

В настоящее время я использую следующую запланированную Облачную функцию для удаления любых Заданий или обязанностей (документов) старше 24 часов. Функция работает нормально, и документы успешно удаляются.

Однако функция сообщает об ОГРОМНОМ количестве операций чтения. Похоже, что каждое отдельное задание или обязанность «читается», независимо от того, нужно ли его удалять или нет. Насколько я понимаю, запросы считаются чтением, если только они не возвращают документ в используемом querySnapshot? Например, Любые документы, которые будут удалены, будут ПРОЧИТАНЫ и УДАЛЕНЫ.

Кто-нибудь знает, как это оптимизировать, чтобы читать только те документы, которые необходимо удалить? Или есть более простой способ удалить старые документы Cloud Firebase с помощью функции Google Cloud? Я бы подумал, что это действительно обычное дело.

* ОБНОВЛЕНО #2 с коллекционной группой и правильным использованием обещаний (Спасибо за вашу помощь!) *

Та же проблема: при запуске функции отображается 844 чтения и 1 Удаление. Других источников, считывающих данные, определенно нет. Скачки происходят только сразу после запуска функции (с помощью Google Cloud Scheduler — Запустите сейчас).

Интересно, что если нет документов, которые нужно удалить, то считывания НЕ записываются. Но если нужно удалить > 1 документ, то будут сотни операций чтения. В настоящее время во всей коллекции всего около 120 пошлин! Кажется, что каждая обязанность читается несколько раз!?

Считывает спайк сразу после запуска функции

введите описание изображения здесь

Спасибо!

 exports.scheduledCleanOldDutiesCollection = functions.pubsub.schedule('0 3 * * *')
    .timeZone('America/Chicago')
    .onRun((context) => {
        const dateYesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));   // 24 hours
        return db.collectionGroup('duties').where('date', '<', dateYesterday).get()
            .then(querySnapshot => {
                const promises = [];
                querySnapshot.forEach(doc => {
                    promises.push(doc.ref.delete());
                });
                return Promise.all(promises);
            });
    });
 

Комментарии:

1. Несколько вопросов: 1) Что именно вы наблюдаете, чтобы измерить ваши показания? 2) Понимаете ли вы, что ваша функция заключается в безусловном чтении каждого отдельного документа в «компаниях» при каждом выполнении? Вы, кажется, не упомянули об этом факте в своем сообщении. Это может дорого обойтись. 3) Вы неправильно обрабатываете обещания при внутреннем чтении и удалении. на самом деле, вы игнорируете множество обещаний. Это самое важное. Ваш код должен возвращать обещание, которое будет выполнено только после завершения всей асинхронной работы, иначе оно будет досрочно прекращено.

2. Чтобы было ясно, я предполагаю, что вы могли бы платить за множество операций чтения документов, которые не приводят к удалению, потому что функция была прекращена до того, как произошло удаление.

3. Привет, Дуг, спасибо за твое сообщение. 1) Мониторинг облачного магазина Firestore и использование облачной базы данных. У меня есть мониторинг в режиме реального времени, и после запуска функции вручную наблюдайте за ее использованием. 2) Да, но в настоящее время существует только 2 компании и 100 заданий. Я не уверен, как избежать чтения «компаний» и добиться того же самого. 3) Я понимаю, о чем вы говорите, но не знаю, как «справиться» с обещанием без «возврата». Тогда я не могу обработать 2-й список…?

4. Я предлагаю провести некоторые поиски того, как эффективно использовать обещания в цикле foreach. Вам нужно будет научиться использовать Promise.all() или изучить синтаксис async/await , или оптимально и то, и другое.

5. Хорошо, я настроил код для использования групп сбора, что устраняет проблемы с обещаниями. Главная проблема-это чтение. Почти 1000 считываний за 1 удаление.

Ответ №1:

Как объяснил Дуг в своем комментарии и в официальной серии видео, ваш код должен возвращать обещание, которое будет выполнено только после завершения всей асинхронной работы, иначе Облачная функция будет досрочно прекращена.

Вы можете адаптировать свой код следующим образом, используя Promise.all() :

 exports.scheduledCleanOldDutiesCollection = functions.pubsub.schedule('0 3 * * *')
    .timeZone('America/Chicago')
    .onRun((context) => {
        const dateYesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));   // 24 hours
        return db.collectionGroup('duties').where('date', '<', dateYesterday).get()
            .then(querySnapshot => {
                const promises = [];
                querySnapshot.forEach(doc => {
                    promises.push(doc.ref.delete());
                });
                return Promise.all(promises);
            });
    });
 

Комментарии:

1. Привет, Рено, Спасибо за это, я действительно ценю помощь. Я изменил код в точности так, как вы показали. Функция работает нормально, но та же проблема остается, когда функция запускается, она сообщает о 844 считываниях и 1 удалении. Я уточню вопрос… Есть какие-нибудь идеи?

2. Привет @Дамиан, я не могу много добавить к тому, что сказал Дуг в своем последнем комментарии. Вы можете получить размер querySnapshot , выполнив .then(querySnapshot => { console.log(querySnapshot.size); .... это .