2017-10-11 37 views
11

Firebaseリアルタイムデータベースでは、親ノードのremove()(ノードは削除され、すべてが子ノードでもあります)を呼び出すだけで、1つのコマンドで大きなアイテムリストを削除できます。Realtime DatabaseのようにCloud Firestoreで「一括」削除コレクションを使用できないのはなぜですか?

しかしFirestore(https://firebase.google.com/docs/firestore/manage-data/delete-data#collections)とマニュアルに従って:私たちは、そのすべてのドキュメントをループをし、それらを一つずつ削除するバッチをコーディングする必要がコレクションを削除する

これは全く効率的ではありません。それはFirestoreがベータ版であるか、または1回の呼び出しで完全ノード(コレクション)を削除することが構造的に不可能なのか?

答えて

11

RTDBは、各データベースが単一の領域に対してローカルなので、これを行うことができます。シリアル化されたビューを提供するために、remove()を呼び出すと、データベースは削除が完了するまで他のすべての作業を停止します。

この現象はいくつかの明らかな停止の原因となっています。remove()コールで膨大な数のデータを削除する必要がある場合、他のすべてのアクティビティは完了するまで効果的にロックアウトされます。その結果、大量のデータを削除したいRTDBユーザであっても、グループ内の文書を再帰的に検索して削除することが推奨されています。

Firestoreは、さまざまなキー範囲が割り当てられている従来のGoogleスタイルのストレージインフラストラクチャに基づいています。ストレージは実際にはBigTableによってサポートされていませんが、同じ原則が適用されます。これは、データを削除することが、必ずしも単一のリージョンアクションではなくなったことを意味し、削除を効果的にトランザクションに見せかけることは非常に高価になります。 Firestoreの取引は現在100人に制限されています。これは、重要ではないトランザクションの一括削除が不可能であることを意味します。

私たちは、有望なトランザクション動作をせずに大量の削除を行うAPIをどのように表面化するのが最適かを調査しています。どのようにモバイルクライアントからこれを行うかを想像するのは簡単ですが、あなたが観察したように、私たちが行ったすべてが埋め込まれていて、あなたのためにバッチ削除ができれば、これは効率的ではありません。また、RESTクライアントを第2世代の市民にすることも望ましくありません。

Firestoreは新製品であり、まだまだたくさんのことがあります。残念ながら、これはちょうどカットをしていません。これは私たちが最終的に取り組むことを望むものですが、私はそれがいつ起こるかについてのタイムラインを提供することはできません。

一方、コンソールとfirebase command-lineは両方とも、これを行うための非トランザクション手段を提供します。テスト自動化のために。

Firestoreをお試しいただきありがとうございます。

+0

Firestoreの文書(質問の@toofooによってリンクされている)の例が間違っていると思います。 'resolve() 'は'(numDeleted == 0) 'のときに呼び出されるべきです。 – Leo

+0

現在、バッチとしてアップロードする必要がありますか?トランザクションを使用できますか? – Leo

+0

そして別の質問。あなたは "有望なトランザクションの振る舞いなしに大量削除"を書いた。私はトランザクションの振る舞いが必要です。私はそれを望むことができますか? – Leo

1

私は、delete()関数をリファクタリングするまで、短いコードと簡単な構文を楽しんで、Realtime DatabaseのFirestore用のアプリをうれしくリファクタリングしていました。サブコレクションを含む文書を削除するには

  • 約束事の配列を作成します。
  • get()サブコレクションは、それ以上サブコレクションを持ちません。
  • forEach()関数を反復して、サブコレクション内の各ドキュメントを読み取ります。
  • 各文書を削除し、削除コマンドを約束の配列に押します。
  • 次のサブコレクションに移動し、これを繰り返します。
  • Promise.all(arrayOfPromises)を使用すると、すべてのサブコレクションが削除されるまで待つことができます。
  • 次に、トップレベルのドキュメントを削除します。
  • あなたは、その後、次のより高い層を得るために別の関数からそれを呼び出す機能ことを確認したいと思うのコレクションや文書のマルチレイヤーで

など

コンソールでこれを見ることができます。コレクションとドキュメントを手動で削除するには、一番右のドキュメントを削除し、一番右のコレクションを削除するなどの作業を行います。

私のコードは、AngularJSです。サブコレクションの前にトップレベルのコレクションが削除されなかった場合にのみ機能します。

$scope.deleteClip = function(docId) { 
if (docId === undefined) { 
docId = $scope.movieOrTvShow + '_' + $scope.clipInMovieModel; 
} 
$scope.languageVideos = longLanguageFactory.toController($scope.language) + 'Videos'; 
var promises = []; 
firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).collection('SentenceTranslations').get() 
.then(function(translations) { 
    translations.forEach(function(doc) { 
    console.log(doc.id); 
    promises.push(firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).collection('SentenceTranslations').doc(doc.id).delete()); 
    }); 
}); 
firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).collection('SentenceExplanations').get() 
.then(function(explanations) { 
    explanations.forEach(function(doc) { 
    console.log(doc.id); 
    promises.push(firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).collection('SentenceExplanations').doc(doc.id).delete()); 
    }); 
}); 
Promise.all(promises).then(function() { 
    console.log("All subcollections deleted."); 
    firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).delete() 
    .then(function() { 
    console.log("Collection deleted."); 
    $scope.clipInMovieModel = null; 
    $scope.$apply(); 
    }) 
    .catch(function(error) { 
    console.log("Remove failed: " + error.message); 
    }); 
}) 
.catch(function(error){ 
    console.log("Error deleting subcollections: " + error); 
}); 
}; 

リアルタイムデータベースではすべて1行だったでしょう。

関連する問題