Cloud Firestore에서 데이터 삭제

다음 예시는 문서, 필드, 컬렉션을 삭제하는 방법을 보여줍니다.

문서 삭제

문서를 삭제하려면 다음과 같은 언어별 delete() 메서드를 사용합니다.

웹 모듈식 API

deleteDoc() 메서드를 사용합니다.

import { doc, deleteDoc } from "firebase/firestore";

await deleteDoc(doc(db, "cities", "DC"));

웹 네임스페이스화된 API

delete() 메서드를 사용합니다.

db.collection("cities").doc("DC").delete().then(() => {
    console.log("Document successfully deleted!");
}).catch((error) => {
    console.error("Error removing document: ", error);
});
Swift

delete() 메서드를 사용합니다.

참고: 이 제품은 watchOS 및 앱 클립 대상에서 사용할 수 없습니다.
do {
  try await db.collection("cities").document("DC").delete()
  print("Document successfully removed!")
} catch {
  print("Error removing document: \(error)")
}
Objective-C

deleteDocumentWithCompletion: 메서드를 사용합니다.

참고: 이 제품은 watchOS 및 앱 클립 대상에서 사용할 수 없습니다.
[[[self.db collectionWithPath:@"cities"] documentWithPath:@"DC"]
    deleteDocumentWithCompletion:^(NSError * _Nullable error) {
      if (error != nil) {
        NSLog(@"Error removing document: %@", error);
      } else {
        NSLog(@"Document successfully removed!");
      }
}];

Kotlin+KTX

delete() 메서드를 사용합니다.

db.collection("cities").document("DC")
    .delete()
    .addOnSuccessListener { Log.d(TAG, "DocumentSnapshot successfully deleted!") }
    .addOnFailureListener { e -> Log.w(TAG, "Error deleting document", e) }

Java

delete() 메서드를 사용합니다.

db.collection("cities").document("DC")
        .delete()
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Log.d(TAG, "DocumentSnapshot successfully deleted!");
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.w(TAG, "Error deleting document", e);
            }
        });

Dart

delete() 메서드를 사용합니다.

db.collection("cities").doc("DC").delete().then(
      (doc) => print("Document deleted"),
      onError: (e) => print("Error updating document $e"),
    );
자바

delete() 메서드를 사용합니다.

// asynchronously delete a document
ApiFuture<WriteResult> writeResult = db.collection("cities").document("DC").delete();
// ...
System.out.println("Update time : " + writeResult.get().getUpdateTime());
Python

delete() 메서드를 사용합니다.

db.collection("cities").document("DC").delete()

Python

delete() 메서드를 사용합니다.

await db.collection("cities").document("DC").delete()
C++

Delete() 메서드를 사용합니다.

db->Collection("cities").Document("DC").Delete().OnCompletion(
    [](const Future<void>& future) {
      if (future.error() == Error::kErrorOk) {
        std::cout << "DocumentSnapshot successfully deleted!" << std::endl;
      } else {
        std::cout << "Error deleting document: " << future.error_message()
                  << std::endl;
      }
    });
Node.js

delete() 메서드를 사용합니다.

const res = await db.collection('cities').doc('DC').delete();
Go

Delete() 메서드를 사용합니다.


import (
	"context"
	"log"

	"cloud.google.com/go/firestore"
)

func deleteDoc(ctx context.Context, client *firestore.Client) error {
	_, err := client.Collection("cities").Doc("DC").Delete(ctx)
	if err != nil {
		// Handle any errors in an appropriate way, such as returning them.
		log.Printf("An error has occurred: %s", err)
	}

	return err
}
PHP

delete() 메서드를 사용합니다.

$db->collection('samples/php/cities')->document('DC')->delete();
Unity

DeleteAsync() 메서드를 사용합니다.

DocumentReference cityRef = db.Collection("cities").Document("DC");
cityRef.DeleteAsync();
C#

DeleteAsync() 메서드를 사용합니다.

DocumentReference cityRef = db.Collection("cities").Document("DC");
await cityRef.DeleteAsync();
Ruby

delete() 메서드를 사용합니다.

city_ref = firestore.doc "#{collection_path}/DC"
city_ref.delete

문서를 삭제하는 경우 Cloud Firestore는 하위 컬렉션 내 문서를 자동으로 삭제하지 않습니다. 따라서 참조를 통해 하위 컬렉션 문서에 액세스할 수 있습니다. 예를 들어 /mycoll/mydoc에서 상위 문서를 삭제했더라도 /mycoll/mydoc/mysubcoll/mysubdoc 경로에 있는 문서에 액세스할 수 있습니다.

존재하지 않는 상위 문서는 콘솔에 표시되지만 쿼리나 스냅샷에는 표시되지 않습니다.

문서를 삭제할 때 하위 컬렉션의 문서까지 삭제하려면 수동으로 삭제해야 합니다. 자세한 내용은 컬렉션 삭제를 참조하세요.

필드 삭제

문서에서 특정 필드를 삭제하려면 문서를 업데이트할 때 다음과 같은 언어별 FieldValue.delete() 메서드를 사용합니다.

웹 모듈식 API

deleteField() 메서드를 사용합니다.

import { doc, updateDoc, deleteField } from "firebase/firestore";

const cityRef = doc(db, 'cities', 'BJ');

// Remove the 'capital' field from the document
await updateDoc(cityRef, {
    capital: deleteField()
});

웹 네임스페이스화된 API

FieldValue.delete() 메서드를 사용합니다.

var cityRef = db.collection('cities').doc('BJ');

// Remove the 'capital' field from the document
var removeCapital = cityRef.update({
    capital: firebase.firestore.FieldValue.delete()
});
Swift

FieldValue.delete() 메서드를 사용합니다.

참고: 이 제품은 watchOS 및 앱 클립 대상에서 사용할 수 없습니다.
do {

  try await db.collection("cities").document("BJ").updateData([
    "capital": FieldValue.delete(),
  ])
  print("Document successfully updated")
} catch {
  print("Error updating document: \(error)")
}
Objective-C

fieldValueForDelete: 메서드를 사용합니다.

참고: 이 제품은 watchOS 및 앱 클립 대상에서 사용할 수 없습니다.
[[[self.db collectionWithPath:@"cities"] documentWithPath:@"BJ"] updateData:@{
  @"capital": [FIRFieldValue fieldValueForDelete]
} completion:^(NSError * _Nullable error) {
  if (error != nil) {
    NSLog(@"Error updating document: %@", error);
  } else {
    NSLog(@"Document successfully updated");
  }
}];

Kotlin+KTX

FieldValue.delete() 메서드를 사용합니다.

val docRef = db.collection("cities").document("BJ")

// Remove the 'capital' field from the document
val updates = hashMapOf<String, Any>(
    "capital" to FieldValue.delete(),
)

docRef.update(updates).addOnCompleteListener { }

Java

FieldValue.delete() 메서드를 사용합니다.

DocumentReference docRef = db.collection("cities").document("BJ");

// Remove the 'capital' field from the document
Map<String,Object> updates = new HashMap<>();
updates.put("capital", FieldValue.delete());

docRef.update(updates).addOnCompleteListener(new OnCompleteListener<Void>() {
    // ...
    // ...

Dart

FieldValue.delete() 메서드를 사용합니다.

final docRef = db.collection("cities").doc("BJ");

// Remove the 'capital' field from the document
final updates = <String, dynamic>{
  "capital": FieldValue.delete(),
};

docRef.update(updates);
자바

FieldValue.delete() 메서드를 사용합니다.

DocumentReference docRef = db.collection("cities").document("BJ");
Map<String, Object> updates = new HashMap<>();
updates.put("capital", FieldValue.delete());
// Update and delete the "capital" field in the document
ApiFuture<WriteResult> writeResult = docRef.update(updates);
System.out.println("Update time : " + writeResult.get());
Python

firestore.DELETE_FIELD 메서드를 사용합니다.

city_ref = db.collection("cities").document("BJ")
city_ref.update({"capital": firestore.DELETE_FIELD})

Python

firestore.DELETE_FIELD 메서드를 사용합니다.

city_ref = db.collection("cities").document("BJ")
await city_ref.update({"capital": firestore.DELETE_FIELD})
C++

FieldValue::Delete() 메서드를 사용합니다.

DocumentReference doc_ref = db->Collection("cities").Document("BJ");
doc_ref.Update({{"capital", FieldValue::Delete()}})
    .OnCompletion([](const Future<void>& future) { /*...*/ });
Node.js

FieldValue.delete() 메서드를 사용합니다.

// Create a document reference
const cityRef = db.collection('cities').doc('BJ');

// Remove the 'capital' field from the document
const res = await cityRef.update({
  capital: FieldValue.delete()
});
Go

firestore.Delete 메서드를 사용합니다.


import (
	"context"
	"log"

	"cloud.google.com/go/firestore"
)

func deleteField(ctx context.Context, client *firestore.Client) error {
	_, err := client.Collection("cities").Doc("BJ").Update(ctx, []firestore.Update{
		{
			Path:  "capital",
			Value: firestore.Delete,
		},
	})
	if err != nil {
		// Handle any errors in an appropriate way, such as returning them.
		log.Printf("An error has occurred: %s", err)
	}

	// ...
	return err
}
PHP

FieldValue::deleteField() 메서드를 사용합니다.

$cityRef = $db->collection('samples/php/cities')->document('BJ');
$cityRef->update([
    ['path' => 'capital', 'value' => FieldValue::deleteField()]
]);
Unity

FieldValue.Delete 메서드를 사용합니다.

DocumentReference cityRef = db.Collection("cities").Document("BJ");
Dictionary<string, object> updates = new Dictionary<string, object>
{
    { "Capital", FieldValue.Delete }
};
C#

FieldValue.Delete 메서드를 사용합니다.

DocumentReference cityRef = db.Collection("cities").Document("BJ");
Dictionary<string, object> updates = new Dictionary<string, object>
{
    { "Capital", FieldValue.Delete }
};
await cityRef.UpdateAsync(updates);
Ruby

firestore.field_delete 메서드를 사용합니다.

city_ref = firestore.doc "#{collection_path}/BJ"
city_ref.update({ capital: firestore.field_delete })

컬렉션 삭제

Cloud Firestore에서 전체 컬렉션 또는 하위 컬렉션을 삭제하려면 컬렉션 또는 하위 컬렉션에 포함된 모든 문서를 검색(읽기)하여 삭제합니다. 이 프로세스에는 읽기 및 삭제 비용이 모두 발생합니다. 컬렉션의 규모가 큰 경우 문서를 조금씩 나누어 삭제하면 메모리 부족 오류를 방지할 수 있습니다. 전체 컬렉션 또는 하위 컬렉션이 삭제될 때까지 이 과정을 반복하세요.

컬렉션을 삭제하려면 제한되지 않은 개별 삭제 요청 수를 조정해야 합니다. 전체 컬렉션은 신뢰할 수 있는 서버 환경에서만 삭제하세요. 모바일 또는 웹 클라이언트에서도 컬렉션을 삭제할 수 있지만, 이 경우 보안 및 성능에 부정적인 영향을 미칩니다.

아래의 스니펫은 다소 단순화되어 있으므로 오류 처리, 보안, 하위 컬렉션 삭제 또는 성능 극대화에 대해서는 다루지 않습니다. 프로덕션 환경에서 컬렉션을 삭제하는 한 가지 추천 방법에 대한 자세한 내용은 컬렉션 및 하위 컬렉션 삭제를 참조하세요.

// Deleting collections from a Web client is not recommended.
Swift
참고: 이 제품은 watchOS 및 앱 클립 대상에서 사용할 수 없습니다.
// Deleting collections from an Apple client is not recommended.
Objective-C
참고: 이 제품은 watchOS 및 앱 클립 대상에서 사용할 수 없습니다.
// Deleting collections from an Apple client is not recommended.
  

Kotlin+KTX

// Deleting collections from an Android client is not recommended.

Java

// Deleting collections from an Android client is not recommended.

Dart

컬렉션은 클라이언트에서 삭제하지 않는 것이 좋습니다.

자바
/**
 * Delete a collection in batches to avoid out-of-memory errors. Batch size may be tuned based on
 * document size (atmost 1MB) and application requirements.
 */
void deleteCollection(CollectionReference collection, int batchSize) {
  try {
    // retrieve a small batch of documents to avoid out-of-memory errors
    ApiFuture<QuerySnapshot> future = collection.limit(batchSize).get();
    int deleted = 0;
    // future.get() blocks on document retrieval
    List<QueryDocumentSnapshot> documents = future.get().getDocuments();
    for (QueryDocumentSnapshot document : documents) {
      document.getReference().delete();
      ++deleted;
    }
    if (deleted >= batchSize) {
      // retrieve and delete another batch
      deleteCollection(collection, batchSize);
    }
  } catch (Exception e) {
    System.err.println("Error deleting collection : " + e.getMessage());
  }
}
Python
def delete_collection(coll_ref, batch_size):
    docs = coll_ref.list_documents(page_size=batch_size)
    deleted = 0

    for doc in docs:
        print(f"Deleting doc {doc.id} => {doc.get().to_dict()}")
        doc.delete()
        deleted = deleted + 1

    if deleted >= batch_size:
        return delete_collection(coll_ref, batch_size)

Python

async def delete_collection(coll_ref, batch_size):
    docs = coll_ref.limit(batch_size).stream()
    deleted = 0

    async for doc in docs:
        print(f"Deleting doc {doc.id} => {doc.to_dict()}")
        await doc.reference.delete()
        deleted = deleted + 1

    if deleted >= batch_size:
        return delete_collection(coll_ref, batch_size)
C++
// This is not supported. Delete data using CLI as discussed below.
  
Node.js
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);
  });
}
Go

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
	"google.golang.org/api/iterator"
)

func deleteCollection(w io.Writer, projectID, collectionName string,
	batchSize int) error {

	// Instantiate a client
	ctx := context.Background()
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return err
	}

	col := client.Collection(collectionName)
	bulkwriter := client.BulkWriter(ctx)

	for {
		// Get a batch of documents
		iter := col.Limit(batchSize).Documents(ctx)
		numDeleted := 0

		// Iterate through the documents, adding
		// a delete operation for each one to the BulkWriter.
		for {
			doc, err := iter.Next()
			if err == iterator.Done {
				break
			}
			if err != nil {
				return err
			}

			bulkwriter.Delete(doc.Ref)
			numDeleted++
		}

		// If there are no documents to delete,
		// the process is over.
		if numDeleted == 0 {
			bulkwriter.End()
			break
		}

		bulkwriter.Flush()
	}
	fmt.Fprintf(w, "Deleted collection \"%s\"", collectionName)
	return nil
}
PHP
function data_delete_collection(string $projectId, string $collectionName, int $batchSize)
{
    // Create the Cloud Firestore client
    $db = new FirestoreClient([
        'projectId' => $projectId,
    ]);
    $collectionReference = $db->collection($collectionName);
    $documents = $collectionReference->limit($batchSize)->documents();
    while (!$documents->isEmpty()) {
        foreach ($documents as $document) {
            printf('Deleting document %s' . PHP_EOL, $document->id());
            $document->reference()->delete();
        }
        $documents = $collectionReference->limit($batchSize)->documents();
    }
}
Unity
// This is not supported. Delete data using CLI as discussed below.
C#
private static async Task DeleteCollection(CollectionReference collectionReference, int batchSize)
{
    QuerySnapshot snapshot = await collectionReference.Limit(batchSize).GetSnapshotAsync();
    IReadOnlyList<DocumentSnapshot> documents = snapshot.Documents;
    while (documents.Count > 0)
    {
        foreach (DocumentSnapshot document in documents)
        {
            Console.WriteLine("Deleting document {0}", document.Id);
            await document.Reference.DeleteAsync();
        }
        snapshot = await collectionReference.Limit(batchSize).GetSnapshotAsync();
        documents = snapshot.Documents;
    }
    Console.WriteLine("Finished deleting all documents from the collection.");
}
Ruby
cities_ref = firestore.col collection_path
query      = cities_ref

query.get do |document_snapshot|
  puts "Deleting document #{document_snapshot.document_id}."
  document_ref = document_snapshot.ref
  document_ref.delete
end

Firebase CLI를 사용한 데이터 삭제

Firebase CLI를 사용해 문서 및 컬렉션을 삭제할 수도 있습니다. 데이터를 삭제하려면 다음 명령어를 사용하세요.

firebase firestore:delete [options] <<path>>

Console을 사용한 데이터 삭제

Console의 Cloud Firestore 페이지에서 문서 및 컬렉션을 삭제할 수 있습니다. Console에서 문서를 삭제하면 하위 컬렉션을 포함하여 해당 문서의 모든 중첩된 데이터가 삭제됩니다.

TTL 정책을 사용하여 데이터 삭제

TTL 정책은 특정 필드를 특정 컬렉션 그룹의 문서 만료 시간으로 지정합니다. TTL 삭제 작업은 문서 삭제 비용에 포함됩니다.

TTL 설정에 대한 자세한 내용은 TTL 정책으로 데이터 보관 관리를 참조하세요.

오류 코드 및 데이터 삭제 시 지연 시간 문제를 해결하는 방법에 대한 자세한 내용은 문제해결 페이지를 참고하세요.

Dataflow를 사용하여 데이터 삭제

Dataflow는 Firestore 데이터베이스에서 일괄 작업을 수행할 수 있는 유용한 도구입니다. Dataflow용 Firestore 커넥터 소개 블로그 게시물에는 컬렉션 그룹의 모든 문서를 삭제하는 예시가 나와 있습니다.