Skip to content

Instantly share code, notes, and snippets.

@gmcabrita
Created July 20, 2020 12:08
Show Gist options
  • Save gmcabrita/edc8a9dbc27048e54fd71ee4d8bcdf0a to your computer and use it in GitHub Desktop.
Save gmcabrita/edc8a9dbc27048e54fd71ee4d8bcdf0a to your computer and use it in GitHub Desktop.
Efficient deletion of a Firestore collection.
package main
import (
"context"
"fmt"
"sync"
"cloud.google.com/go/firestore"
firebase "firebase.google.com/go"
)
var (
gcpProject = "foo"
collection = "bar"
)
func deleteCollection(ctx context.Context, client *firestore.Client,
ref *firestore.CollectionRef) {
type Deletes struct {
sync.Mutex
count int
}
var (
lastSeen *firestore.DocumentSnapshot
wg sync.WaitGroup
del Deletes
)
for {
q := ref.Select().OrderBy(firestore.DocumentID, firestore.Asc).Limit(500)
if lastSeen != nil {
q = q.StartAfter(lastSeen)
}
docs, err := q.Documents(ctx).GetAll()
if err != nil || len(docs) == 0 {
break
}
lastSeen = docs[len(docs)-1]
wg.Add(1)
go func(docs []*firestore.DocumentSnapshot) {
defer wg.Done()
numDeleted := 0
batch := client.Batch()
for _, doc := range docs {
batch.Delete(doc.Ref)
numDeleted++
}
if numDeleted == 0 {
return
}
_, err := batch.Commit(ctx)
if err == nil {
del.Lock()
del.count += len(docs)
del.Unlock()
fmt.Printf("\rDocuments deleted: %d", del.count)
}
}(docs)
}
wg.Wait()
fmt.Println("\nDone!")
}
func main() {
ctx := context.Background()
conf := &firebase.Config{ProjectID: gcpProject}
app, err := firebase.NewApp(ctx, conf)
if err != nil {
fmt.Println(err)
return
}
client, err := app.Firestore(ctx)
if err != nil {
fmt.Println(err)
return
}
deleteCollection(ctx, client, client.Collection(collection))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment