Облачная функция, которая перемещает документы между коллекциями - PullRequest
0 голосов
/ 06 июля 2019

У меня есть три коллекции: «прошлое», «сегодня» и «будущее».

«коллекция сегодня» должна иметь только один документ.

В полночь мне нужнонайти в моей «будущей» коллекции документ с полем «следующий» или, если такого документа нет, найти тот, который имеет значение в поле «число» ближе всего к значению в поле «номер» документа в моем »коллекция "сегодня". Затем мне нужно переместить документ "сегодня" в коллекцию "прошлое", а также переместить найденный документ из коллекции "будущее" в коллекцию "сегодня".

НасколькоЯ понимаю, что нет метода "перемещения", поэтому я должен использовать комбинацию удалений и созданий, которые должны быть выполнены в одной транзакции.

Я понял, как сделать часть "планировщика", но могуНе могу понять, как закодировать остальное (фактическое перемещение документов).

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const firestore = admin.firestore();    

exports.scheduledFunction = functions.pubsub.schedule('0 0 * * *')
.onRun((context) => {

  //I need to move my documents... 
});

Не могли бы вы помочь мне с кодом, пожалуйста?

1 Ответ

0 голосов
/ 06 июля 2019

Возможно, вы ищете документацию не в том месте. Его нет в Firestore / Extend с облачными функциями. Это в базовой документации Firestore, но вы должны переключить тип кода на node-js. https://firebase.google.com/docs/firestore/query-data/order-limit-data

Вы должны собирать данные по двум запросам: в сегодняшних и будущих коллекциях. По этим запросам вы получаете документы и их данные. Чем вам просто нужно сделать документ в прошлом, удалить и сделать новый документ (или переписать существующий) сегодня и удалить в будущем.

Вот как я мог бы сделать это в простой вызываемой функции:

exports.scheduledFunction = functions.pubsub.schedule('0 0 * * *')
.onRun(async (context) => {
    try {
        let queryToday = admin.firestore().collection('today'); //you can add .limit(1)
        const todaySnapshot = await queryToday.get();
        const todayDoc = todaySnapshot.docs[0];
        const todayData = todayDoc.data();
        const todayToPastRef = admin.firestore().doc(`past/${todayData.documentUid}`);
        /* or how the id is stored? you can just call 
        const todayToPastRef = admin.firestore().collection('past').doc()
        and it will be generated automatically
        */
        const promises = [];
        promises.push(todayToPastRef.set(todayData));
        let queryFuture = admin.firestore().collection('future').orderBy('date').limit(1);
        /*
        or how is the date stored? Idk if firebase allows to query by Timestamp
        you just want to fetch the closest date after today so the order is ascending
        */
        const futureSnapshot = await queryFuture.get();
        const futureDoc = futureSnapshot.docs[0];
        const futureData = futureDoc.data();
        const futureToTodayRef = admin.firestore().doc(`today/${futureData.documentUid}`);
        promises.push(futureToTodayRef.set(todayData));
        promises.push(futureDoc.ref.delete());

        promises.push(todayDoc.ref.delete());
        /*
        or you can try to change today's doc data, but the id will remain the same
        promises.push(todayDoc.ref.update(futureData))
        */
        return Promise.all(promises); // function will be executed after all the promises are fullfilled or rejected
    } catch (err) {
        return Promise.reject(err);
    }
});

Обратите внимание, что вместо .then () и .catch () я использую async / await.

Используйте console.log () для отладки и попробуйте VSCode, чтобы вы могли проверять методы и свойства объектов, что очень полезно

UPDATE: Да, вы можете сделать это с помощью пакета. Есть еще один пример:

exports.scheduledFunction = functions.pubsub.schedule('0 0 * * *').onRun((context) => {
    const db = admin.firestore();
    let queryToday = db.collection('today');    
    let queryFuture = db.collection('future').orderBy('date').limit(1);
    const batch = db.batch();
    return queryToday
        .get()
        .then(todaySnapshot => {
            const todayDoc = todaySnapshot.docs[0];
            const todayData = todayDoc.data();
            const todayToPastRef = db.doc(`past/${todayData.docUid}`);
            batch.set(todayToPastRef, todayData);
            batch.delete(todayDoc.ref);
            return queryFuture.get();
        })
        .then(futureSnapshot => {
            const futureDoc = futureSnapshot.docs[0];
            const futureData = futureDoc.data();
            const futureToTodayRef = db.doc(`today/${futureData.docUid}`);
            batch.set(futureToTodayRef, futureData);
            batch.delete(futureDoc.ref);
            // now two operations are completed, you just can commit the batch
            return batch.commit();
        })
        .catch(err => {
            // if todaySnapshot or futureSnapshot were not fetched, batch wont be commited
            // or, for example, if snapshots were empty
            return Promise.reject(err)
        });
});

Вы также можете получать документы параллельно с .getAll () или чем-то в этом роде. Вы должны проверить и поэкспериментировать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...