云功能可在集合之间移动文档

时间:2019-07-06 15:28:20

标签: google-cloud-firestore google-cloud-functions

我有三个集合:“过去”,“今天”和“未来”。

“今天”集合应该只有一个文档。

在午夜时分,我需要在“未来”集合中找到一个包含“下一个”字段的文档,或者,如果没有这样的文档,请在“数字”字段中找到一个值比“我的“今天”收藏中的文档编号”字段。然后,我需要将“今天”的文档移至“过去”收藏夹,并将找到的文档从“未来”收藏夹移至“今天”收藏夹。

据我了解,没有“移动”方法,因此我必须使用删除和创建的组合,这需要在一个事务中完成。

我想出了如何执行“调度程序”部分,但无法弄清楚如何编写其余部分(文档的实际移动)。

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 :(得分:0)

可能是我在错误的位置寻找文档。它不在Firestore /具有云功能的扩展中。它在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);
    }
});

请注意,不要使用async / await来代替.then()和.catch()。

使用console.log()进行调试,然后尝试使用VSCode,以便您可以检查对象上的方法和属性,这非常有帮助

更新: 是的,您可以批量进行。还有另一个例子:

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()或类似的内容并行获取文档。您应该测试和尝试