How to add timestamp to every collection insert,update in Cloud Functions for firestore database

后端 未结 6 533
心在旅途
心在旅途 2020-11-29 09:23

I have a firestore collection called Posts I make an insert on the client side and it works.

I want to add the createdAt and updatedAt fields to every insert in my p

6条回答
  •  余生分开走
    2020-11-29 10:29

    This solution supports first-level subcollections and is based off @Jonathan's answer above:

    **
     * writes fields common to root-level collection records that are generated by the
     * admin SDK (backend):
     * - createdAt (timestamp)
     * - updatedAt (timestamp)
     */
    exports.createCommonFields = functions.firestore
    .document('{colId}/{docId}')
    .onWrite(async (change, context) => {
        // the collections you want to trigger
        const setCols = ['posts', 'reviews', 'comments', ];
    
        // run the field creator if the document being touched belongs to a registered collection
        if (setCols.includes(context.params.colId)) {
            console.log(`collection ${context.params.colId} is not registered for this trigger`);
            return null;
        } else {
            console.log(`running createCommonFields() for collection: ${context.params.colId}`);
        }
    
        // cause the creation of timestamp fields only
        _createCommonFields(change);
    });
    
    /**
     * createCommonFields' equivalent for sub-collection records
     */
    exports.createCommonFieldsSubColl = functions.firestore
    .document('{colId}/{colDocId}/{subColId}/{subColDocId}')
    .onWrite(async (change, context) => {
        console.log(`collection: ${context.params.colId}, subcollection: ${context.params.subColId}`);
    
        // the subcollections of the collections you want to trigger
        // triggers for documents like 'posts/postId/versions/versionId, etc
        const setCols = {
            'posts': ['versions', 'tags', 'links', ], 
            'reviews': ['authors', 'versions'],
            'comments': ['upvotes', 'flags'],
        };
    
        // parse the collection and subcollection names of this document
        const colId = context.params.colId;
        const subColId = context.params.subColId;
        // check that the document being triggered belongs to a registered subcollection
        // e.g posts/versions; skip the field creation if it's not included
        if (setCols[colId] && setCols[colId].includes(subColId)) {
            console.log(`running createCommonFieldsSubColl() for this subcollection`);
        } else {
            console.log(`collection ${context.params.colId}/${context.params.subColId} is not registered for this trigger`);
            return null;
        }
    
        // cause the creation of timestamp fields
        _createCommonFields(change);
    });
    
    /**
     * performs actual creation of fields that are common to the
     * registered collection being written
     * @param {QueryDocumentSnapshot} change a snapshot for the collection being written
     */
    async function _createCommonFields(change) {
        // simplify event types
        const createDoc = change.after.exists && !change.before.exists;
        const updateDoc = change.before.exists && change.after.exists;
        const deleteDoc = change.before.exists && !change.after.exists;
    
        if (deleteDoc) {
            return null;
        }
    
        // simplify input data
        const after = change.after.exists ? change.after.data() : null;
        const before = change.before.exists ? change.before.data() : null;
    
        // prevent update loops from triggers
        const canUpdate = () => {
            // if update trigger
            if (before.updatedAt && after.updatedAt) {
                if (after.updatedAt._seconds !== before.updatedAt._seconds) {
                    return false;
                }
            }
            // if create trigger
            if (!before.createdAt && after.createdAt) {
                return false;
            }
            return true;
        }
    
        const currentTime = admin.firestore.FieldValue.serverTimestamp();
        // add createdAt
        if (createDoc) {
            return change.after.ref.set({
                createdAt: currentTime,
                updatedAt: currentTime,
            }, { merge: true })
            .catch((e) => {
                console.log(e);
                return false;
            });
        }
        // add updatedAt
        if (updateDoc && canUpdate()) {
            return change.after.ref.set({
                updatedAt: currentTime,
            }, { merge: true })
            .catch((e) => {
                console.log(e);
                return false;
            });
        }
        return null;
    }
    

提交回复
热议问题