簡體   English   中英

Firestore 刪除不存在的祖先文檔和子集合

[英]Firestore delete non-existent ancestor documents and sub-collection

我想清理我的收藏數據。 我有集合名稱"teams" 它有數據和子集合名稱“玩家”

我已經通過 Firestore 的簡單刪除查詢刪除了“團隊”文檔,但正如我們所知,我們無法通過刪除主/祖先 docID 來刪除子集合(玩家) 我們必須從“玩家”集合中獲取所有文檔,然后首先刪除它們。 之后我們應該刪除祖先(團隊的文檔)文檔,以便清除所有集合。

不可能從“團隊”集合中獲取那些孤立的文檔。 那么從集合中清除這些文檔的方法是什么?

我要刪除所有文件(斜體)

~ PS:我已經創建了一個 firebase 雲函數來刪除子集合文檔,同時刪除祖先文檔。

exports.deleteOrphanedTeamsDoc = functions.firestore
  .document('teams/{teamID}')
  .onDelete(async (snap, context) => {
    var teamID = context.params.teamID;
    console.log("Deleted teamID --->>> " + teamID);

    const store = admin.firestore();
    var teamsPlayer = await store.collection('teams').doc(teamID).collection('players').get()

    teamsPlayer.docs.forEach(async(val) => {
      await store.collection('teams').doc(teamID).collection('players').doc(val.id).delete();
    });
  });

因此,在上述代碼的幫助下,我也可以刪除帶有子集合的新團隊 docID。

但是我的“團隊”集合中所有可用的孤立文檔呢?

更新 1:

我嘗試了Renaud Tarnec的代碼,對不起,但我是新手,所以沒有太多想法。 我點擊了運行按鈕,但遇到了一些問題

在此處輸入圖片說明

6:46:13.625 pm
scheduledFunction
Function execution took 12608 ms, finished with status: 'error'
6:46:13.622 pm
scheduledFunction
at processTicksAndRejections (internal/process/task_queues.js:97:5)
6:46:13.622 pm
scheduledFunction
at runMicrotasks (<anonymous>)
6:46:13.622 pm
scheduledFunction
at /workspace/index.js:161:53
6:46:13.622 pm
scheduledFunction
ReferenceError: promises is not defined 
6:46:01.018 pm
scheduledFunction
Function execution started

我認為問題在這里ReferenceError: promises is not defined at

const parentsSnapshotsArray = await Promise.all(promises);

但是我的“團隊”集合中所有可用的孤立文檔呢?

正如您所提到的,您的雲功能不會為已刪除的teams文檔觸發。

要刪除孤立player文檔,您可以做的是每 X 分鍾/小時運行一次預定的雲功能。

以下 Cloud Function 使用CollectionGroup 查詢來獲取所有player文檔並刪除它們。 請注意,您需要有一個用於查詢的 Firestore 索引。 還要注意我們如何使用Promise.all()在所有異步工作完成后返回一個唯一的 Promise; 這是 正確管理 Cloud Function 生命周期的關鍵。

exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {

    const playersRef = admin.firestore().collectionGroup('players');
    const playersSnap = await playersRef.get();

    const promises = [];
    playersSnap.forEach((doc) => {
        promises.push(doc.ref.delete());
    });
    return Promise.all(promises)

});

現在,我們需要添加一個額外的業務邏輯。 僅當父team文檔不存在時,才應刪除player文檔。

以下代碼應該可以解決問題(未經測試):

exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun(async (context) => {

    const playersRef = admin.firestore().collectionGroup('players');
    const playersSnap = await playersRef.get();

    const docParentIdsToDelete = [];

    const docParentIdsTreated = [];
    const promisesParentDocs = [];
    playersSnap.forEach((doc) => {
        const parentTeamRef = doc.ref.parent.parent;
        const parentTeamId = parentTeamRef.id;
        if (docParentIdsTreated.indexOf(parentTeamId) < 0) {
            // We need to check if the parent exists
            promisesParentDocs.push(parentTeamRef.get());
            docParentIdsTreated.push(parentTeamId);
        }
    });

    const parentsSnapshotsArray = await Promise.all(promisesParentDocs);

    parentsSnapshotsArray.forEach(snap => {
        if (!snap.exists) {
            // The parent team doc DOES NOT exist. It is shown in italic in the Firebase console.
            // => We need to delete the players child docs
            docParentIdsToDelete.push(snap.id);
        }
    });
    
    const promisesDeletion = [];
    playersSnap.forEach((doc) => {
        const parentTeamId = doc.ref.parent.parent.id;
        if (docParentIdsToDelete.indexOf(parentTeamId) > -1) {
            // We need to delete the player doc
            promisesDeletion.push(doc.ref.delete());
        }
    });
    
    return Promise.all(promisesDeletion);
    
});

基本上,我們首先獲取所有player文檔。 然后我們循環檢查父team文檔是否存在(使用數組來最小化查詢數量)。 如果它不存在,我們將它的 ID 推送到一個數組 => 需要刪除player子文檔。 然后我們再次在player文檔上循環並刪除所需的文檔(再次將刪除承諾推送到傳遞給Promise.all()的數組)。 可能有一些優化代碼和減少循環次數的空間,但邏輯是存在的(如果我沒有做錯:-))。

Firebase 控制台通過這些斜體文件表明,這些文件實際上並不存在。 這些文檔不存在,要么是因為您沒有創建它們,要么是您明確刪除了它們。 所以這些文檔仍然顯示,因為它們下面有一個子集合。 所以基本上文檔的 ID 會以某種方式保留,如果您將來需要進行某些操作。

需要記住的一件事是,在 Cloud Firestore 中,文檔和子集合不像文件系統文件和目錄那樣工作。 所以總而言之,你不能刪除不存在的東西。 換句話說,由於該位置沒有物理文檔,因此您無法執行刪除操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM