使用Firebase中的函数如何删除一个集合?

huangapple go评论65阅读模式
英文:

how do i delete a collection using functions in firebase?

问题

I want to delete a specific collection using a schedule.

const functions = require("firebase-functions");

const { initializeApp, applicationDefault, cert } = require('firebase-admin/app');
const { getFirestore, Timestamp, FieldValue } = require('firebase-admin/firestore');

initializeApp();

const db = getFirestore();

exports.scheduledFunction = functions.pubsub.schedule('10 9 * * 1').timeZone('Asia/Seoul').onRun(
    (context) => {
        deleteCollection(db, "/ranking", 100);
    }
)

async function deleteCollection(db, collectionPath, batchSize) {
  const collectionRef = db.collection(collectionPath);
  const query = collectionRef.orderBy('__name__').limit(batchSize);

  return new Promise((resolve, reject) => {
    deleteQueryBatch(db, query, resolve).catch(reject);
  });
}

async function deleteQueryBatch(db, query, resolve) {
  const snapshot = await query.get();

  const batchSize = snapshot.size;
  if (batchSize === 0) {
    // When there are no documents left, we are done
    resolve();
    return;
  }

  // Delete documents in a batch
  const batch = db.batch();
  snapshot.docs.forEach((doc) => {
    batch.delete(doc.ref);
  });
  await batch.commit();

  // Recurse on the next process tick, to avoid
  // exploding the stack.
  process.nextTick(() => {
    deleteQueryBatch(db, query, resolve);
  });
}

ERROR:

{
  "insertId": "1debz6yf3nc8aa",
  "jsonPayload": {
    "@type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished",
    "targetType": "PUB_SUB",
    "status": "UNAUTHENTICATED",
    "pubsubTopic": "projects/run-and-hit-32486390/topics/firebase-schedule-scheduledFunction-us-central1",
    "jobName": "projects/run-and-hit-32486390/locations/asia-south1/jobs/firebase-schedule-scheduledFunction-us-central1"
  },
  "resource": {
    "type": "cloud_scheduler_job",
    "labels": {
      "job_id": "firebase-schedule-scheduledFunction-us-central1",
      "project_id": "run-and-hit-32486390",
      "location": "asia-south1"
    }
  },
  "timestamp": "2023-04-17T00:10:02.623192583Z",
  "severity": "ERROR",
  "logName": "projects/run-and-hit-32486390/logs/cloudscheduler.googleapis.com%2Fexecutions",
  "receiveTimestamp": "2023-04-17T00:10:02.623192583Z"
}

It seems like an authentication issue, but it seems to work if I force it to run in the cloud.

I registered the schedule code and expected the data to be deleted at the set time, but an error occurred.

英文:

i want to delete a specific collection using a schedule.

const functions = require("firebase-functions");

const { initializeApp, applicationDefault, cert } = require('firebase-admin/app');
const { getFirestore, Timestamp, FieldValue } = require('firebase-admin/firestore');

initializeApp();

const db = getFirestore();

exports.scheduledFunction = functions.pubsub.schedule('10 9 * * 1').timeZone('Asia/Seoul').onRun(
    (context) => {
        deleteCollection(db, "/ranking", 100);
    }
)

async function deleteCollection(db, collectionPath, batchSize) {
  const collectionRef = db.collection(collectionPath);
  const query = collectionRef.orderBy('__name__').limit(batchSize);

  return new Promise((resolve, reject) => {
    deleteQueryBatch(db, query, resolve).catch(reject);
  });
}

async function deleteQueryBatch(db, query, resolve) {
  const snapshot = await query.get();

  const batchSize = snapshot.size;
  if (batchSize === 0) {
    // When there are no documents left, we are done
    resolve();
    return;
  }

  // Delete documents in a batch
  const batch = db.batch();
  snapshot.docs.forEach((doc) => {
    batch.delete(doc.ref);
  });
  await batch.commit();

  // Recurse on the next process tick, to avoid
  // exploding the stack.
  process.nextTick(() => {
    deleteQueryBatch(db, query, resolve);
  });
}

ERROR:

{
  "insertId": "1debz6yf3nc8aa",
  "jsonPayload": {
    "@type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished",
    "targetType": "PUB_SUB",
    "status": "UNAUTHENTICATED",
    "pubsubTopic": "projects/run-and-hit-32486390/topics/firebase-schedule-scheduledFunction-us-central1",
    "jobName": "projects/run-and-hit-32486390/locations/asia-south1/jobs/firebase-schedule-scheduledFunction-us-central1"
  },
  "resource": {
    "type": "cloud_scheduler_job",
    "labels": {
      "job_id": "firebase-schedule-scheduledFunction-us-central1",
      "project_id": "run-and-hit-32486390",
      "location": "asia-south1"
    }
  },
  "timestamp": "2023-04-17T00:10:02.623192583Z",
  "severity": "ERROR",
  "logName": "projects/run-and-hit-32486390/logs/cloudscheduler.googleapis.com%2Fexecutions",
  "receiveTimestamp": "2023-04-17T00:10:02.623192583Z"
}

it seems like an authentication issue, but it seems to work if i force it to run in the cloud.

i registered the schedule code and expected the data to be deleted at the set time, but an error occurred.

答案1

得分: 2

如@samthecodingman在评论中建议的那样,在deleteCollection(db, "/ranking", 100)之前,您忘记添加return语句。

另外,您可以查看文档,Firebase文档还提供了一个示例Firebase函数代码段,用于删除集合。

/**
 * 启动递归删除给定路径的文档。
 *
 * 调用用户必须经过身份验证,并且在身份验证令牌上设置了自定义“admin”属性为true。
 *
 * 此删除不是原子操作,可能在仅删除一些文档后失败。
 *
 * @param {string} data.path 要删除的文档或集合路径。
 */
exports.recursiveDelete = functions
  .runWith({
    timeoutSeconds: 540,
    memory: '2GB'
  })
  .https.onCall(async (data, context) => {
    // 仅允许管理员用户执行此函数。
    if (!(context.auth && context.auth.token && context.auth.token.admin)) {
      throw new functions.https.HttpsError(
        'permission-denied',
        '必须是管理员用户才能启动删除操作。'
      );
    }

    const path = data.path;
    console.log(
      `用户 ${context.auth.uid} 请求删除路径 ${path}`
    );

    // 对给定的文档或集合路径运行递归删除。
    // 必须在functions配置中设置“token”,可以通过运行“firebase login:ci”命令在命令行中生成它。
    await firebase_tools.firestore
      .delete(path, {
        project: process.env.GCLOUD_PROJECT, 
        recursive: true,
        force: true,
        token: functions.config().fb.token
      });

    return {
      path: path 
    };
  });

注意:您将需要使用Firebase控制台项目设置中可以找到的同一Firebase项目的GCLOUD_PROJECT ID。

英文:

As @samthecodingman suggested in the comments, you missed adding a return statement before the line deleteCollection(db, "/ranking", 100).

Also Instead using your own code snippet to delete a collection using functions in a Firebase. You can check with this Documentation, where Firebase Docs has also provided a sample firebase function code snippet to delete the collection:

/**
 * Initiate a recursive delete of documents at a given path.
 * 
 * The calling user must be authenticated and have the custom "admin" attribute
 * set to true on the auth token.
 * 
 * This delete is NOT an atomic operation and it's possible
 * that it may fail after only deleting some documents.
 * 
 * @param {string} data.path the document or collection path to delete.
 */
exports.recursiveDelete = functions
  .runWith({
    timeoutSeconds: 540,
    memory: '2GB'
  })
  .https.onCall(async (data, context) => {
    // Only allow admin users to execute this function.
    if (!(context.auth && context.auth.token && context.auth.token.admin)) {
      throw new functions.https.HttpsError(
        'permission-denied',
        'Must be an administrative user to initiate delete.'
      );
    }

    const path = data.path;
    console.log(
      `User ${context.auth.uid} has requested to delete path ${path}`
    );

    // Run a recursive delete on the given document or collection path.
    // The 'token' must be set in the functions config, and can be generated
    // at the command line by running 'firebase login:ci'.
    await firebase_tools.firestore
      .delete(path, {
        project: process.env.GCLOUD_PROJECT, 
        recursive: true,
        force: true,
        token: functions.config().fb.token
      });

    return {
      path: path 
    };
  });

Note : You will be requiring the GCLOUD_PROJECT id of the same firebase project which you can find in the project settings of the firebase console.

huangapple
  • 本文由 发表于 2023年4月17日 09:23:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76031141.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定