如何在创建新文档时设置批量删除(使用触发器)

时间:2019-06-24 08:31:36

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

我正在使用带有集合引用url/{newDocs}的Firestore创建一个URL缩短项目(firebase的新功能) 对于每个新文档架构,如下所示:

let schema = {
  code: codeGeneratedbyShortidPackage,
  url: req.body.URL,
  expiredAt: Date.now()+60000  // in milisceonds i.e 10 mins for 600000
}

我的问题是,如何在Firestore中的上述参考处添加新文档时,为每个文档中超过其时间限制的每个文档设置批量删除。

我尝试了以下代码,但是没有用。


exports.deleteFunc = functions.firestore.document('url/{docId}').onCreate( ( change, context) => {
   
   let newbatch = db.batch() ;
   db.collection('nonauth_url').where( 'expiredAt' , '<=', Date.now()).get().then( (snapshot) => {
  snapshot.forEach( (doc) => {
     newbatch.delete(doc.ref) ;
  }) ;
   }).then( () => {
  console.log('Delete done') ;
   }) ;
   return newbatch.commit().then( () => {
  console.log('Batch Committed');
   }).catch( (err) => {
  console.error('error occurred', err) ;
   }) ;
}) ;

3 个答案:

答案 0 :(得分:1)

@ renaud-tarnec提供的云功能的Javascript版本 https://stackoverflow.com/a/56735180/9646878

对于上述答案的Typescript变体

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import { HttpsError } from 'firebase-functions/lib/providers/https';
admin.initializeApp(functions.config().firebase);

export const onDelete = functions.firestore.document('url/{documentId}')
    .onDelete(async (snap, context) => {

        const docId = context.params.documentId;

        const db = await admin.firestore();
        const newbatch = db.batch();

        try {
            const someHistory = await db.collection('nonauth_url')
                                     .where('expiredAt', '<=', Date.now())
                                     .get();
            someHistory.forEach(history => {
                newbatch.delete(history.ref);
            });
            return newbatch.commit();
        } catch (err) {
            console.error('error occurred', err);
            throw new HttpsError('internal', 'Internal Server Error');
        }
    }); 

答案 1 :(得分:0)

以下代码可以解决问题:

exports.deleteFunc = functions.firestore
  .document('url/{docId}')
  .onCreate((change, context) => {
    const db = admin.firestore();
    let newbatch = db.batch();

    return db
      .collection('nonauth_url')
      .where('expiredAt', '<=', Date.now())
      .get()
      .then(snapshot => {
        snapshot.forEach(doc => {
          newbatch.delete(doc.ref);
        });

        return newbatch.commit();
      })
      .catch(err => {
        console.error('error occurred', err);
      });
  });

请注意,您必须在后台触发的Cloud Function中返回Promise或值。我建议您观看Firebase视频系列中有关“ JavaScript承诺”的3个视频:https://firebase.google.com/docs/functions/video-series/,它们解释了这一要点。

答案 2 :(得分:0)

这是我的项目的index.js和index.html

<h1>URL Shortner !!</h1>
    <hr>
    <form method="POST" action="/parse-url">
      <input type="url" name="url" id="url"><br>
      <button type="submit" id="submit">Submit</button>
    </form>
    <h1 id="newurl"></h1>

const functions = require('firebase-functions');
const admin = require('firebase-admin') ;
const express = require('express') ;
const urlId = require('shortid') ;

const sp = require('synchronized-promise') ;

const serviceAccount = require('./url-shortner-2596201e2cac.json') ;

const app = express() ;

admin.initializeApp({
   credential: admin.credential.cert(serviceAccount)
});

let db = admin.firestore() ;
let Data = db.collection('nonauth_url') ;

app.post('/parse-url', (req, res) => {

   let codeGenerated = urlId.generate() ;

   let docname = 'url_doc-' + codeGenerated ;

   let schema = {
      code: codeGenerated,
      url: req.body.URL,
      expiredAt: Date.now()+600000  // in milisceonds
   }

   let database = Data.doc(docname).set(schema) ;
   res.send(schema.code) ;
}) ;

const getDatasPromise = () => {
   return new Promise((resolve, reject) => {
       let events = [];
       const dataRetrieve = Data.get()
           .then((snapshot) => {
               snapshot.forEach((doc) => events.push(doc.data()));
               resolve(events); // return the events only after they are fetched
           })
           .catch(error => {
               reject(error);
           });
   });
};

app.get('/:code', (req, res) =>{
   let url_code = req.params.code ;
   let target_url ;
   if( urlId.isValid(url_code) ){
      
      let syncFunc = sp(getDatasPromise) ;
      let dataArr = syncFunc() ;

      dataArr.forEach( (doc) => {
         if( doc.code === url_code && ( doc.expiredAt > Date.now() ) ){
            target_url = doc.url ;
         }
      }) ;
      if( target_url !== undefined){
         res.redirect(target_url) ;
      }
      else{
         console.log('url not found') ;
         res.status(404).redirect('404.html') ;
      }
   }
   else{
      res.status(404).redirect('404.html') ;
   }
}) ;

// Create and Deploy Your First Cloud Functions
// https://firebase.google.com/docs/functions/write-firebase-functions

exports.routeFunc = functions.https.onRequest(app) ;

exports.deleteFunc = functions.firestore.document('/nonauth_url/{docId}').onCreate( ( change, context) => {
   
   let database = admin.firestore() ;
   let newbatch = database.batch() ;

   return database.collection('nonauth_url').where('expiredAt', '<=', Date.now())
      .get()
      .then( (snapshot) => {
         snapshot.forEach( doc => {
            newbatch.delete(doc.ref) ;
         }) ;
         return newbatch.commit() ;
      })
      .catch( (err) => {
         console.error('error occurred', err) ;
      }) ;
}) ;

问题发生在deleteFunc