Firestore가 하나의 쿼리를 사용하여 조건에 맞는 여러 문서를 업데이트할 수 있습니까?
즉, SQL에서 이와 동등한 Firestore가 무엇인지 파악하려고 합니다.
UPDATE table SET field = 'foo' WHERE <condition>`
예, 여러 문서를 한 번에 업데이트하는 방법을 묻는 것입니다. 하지만 연결된 질문과 달리, 특정 조건에 맞는 모든 문서에 플래그를 설정하기만 하면 되기 때문에 메모리에 아무것도 읽지 않고 한 번에 업데이트하는 방법을 묻는 것입니다.
db.collection('table')
.where(...condition...)
.update({
field: 'foo',
});
제가 기대했던 대로입니다. CollectionReference에는 다음이 없습니다..update방법.
트랜잭션 및 일괄 처리된 쓰기 설명서에는 트랜잭션 및 일괄 처리된 쓰기가 나와 있습니다.트랜잭션은 "트랜잭션은 임의의 수의 get() 작업에 이어 임의의 수의 쓰기 작업으로 구성됩니다." 일괄 처리된 쓰기는 문서별로 작동하므로 해결책이 아닙니다.
MongoDB를 사용하면, 이것은
db.table.update(
{ /* where clause */ },
{ $set: { field: 'foo' } }
)
그렇다면 Firestore는 SQL 데이터베이스 또는 MongoDB가 작동하는 방식, 즉 각 문서에 대해 클라이언트를 왕복할 필요 없이 하나의 쿼리로 여러 문서를 업데이트할 수 있습니까?그렇지 않다면 어떻게 효율적으로 이 작업을 수행할 수 있습니까?
Cloud Firestore에서 문서를 업데이트하려면 ID를 알아야 합니다.Cloud Firestore는 SQL의 업데이트 쿼리와 동일한 쿼리를 지원하지 않습니다.
이 작업은 항상 두 단계로 수행해야 합니다.
- 문서 ID를 결정하기 위해 사용자 조건으로 쿼리 실행
- 개별 업데이트 또는 하나 이상의 일괄 작성으로 문서를 업데이트합니다.
1단계의 문서 ID만 필요합니다.따라서 ID만 반환하는 쿼리를 실행할 수 있습니다.클라이언트 측 SDK에서는 이 작업을 수행할 수 없지만 다음과 같이 REST API 및 Admin SDK를 통해 수행할 수 있습니다.Cloud Firestore 컬렉션에서 문서 ID 목록을 가져오는 방법은 무엇입니까?
프랭크의 대답은 사실 훌륭하고 문제를 해결합니다.
하지만 서두르는 사람들에게 이 토막글은 다음과 같은 도움이 될 수 있습니다.
const updateAllFromCollection = async (collectionName) => {
const firebase = require('firebase-admin')
const collection = firebase.firestore().collection(collectionName)
const newDocumentBody = {
message: 'hello world'
}
collection.where('message', '==', 'goodbye world').get().then(response => {
let batch = firebase.firestore().batch()
response.docs.forEach((doc) => {
const docRef = firebase.firestore().collection(collectionName).doc(doc.id)
batch.update(docRef, newDocumentBody)
})
batch.commit().then(() => {
console.log(`updated all documents inside ${collectionName}`)
})
})
}
내부 내용만 변경하면 됩니다.where데이터를 쿼리하는 함수와newDocumentBody그것이 모든 문서에서 변경되는 것입니다.
또한 컬렉션의 이름으로 함수를 호출하는 것도 잊지 마십시오.
가장 간단한 방법은 다음과 같습니다.
const ORDER_ITEMS = firebase.firestore().collection('OrderItems')
ORDER_ITEMS.where('order', '==', 2)
.get()
.then(snapshots => {
if (snapshots.size > 0) {
snapshots.forEach(orderItem => {
ORDER_ITEMS.doc(orderItem.id).update({ status: 1 })
})
}
})
Dart / Float 사용자용(Renato Trombini Neto에서 편집)
// CollectionReference collection = FirebaseFirestore.instance.collection('something');
// This collection can be a subcollection.
_updateAllFromCollection(CollectionReference collection) async {
var newDocumentBody = {"username": ''};
User firebaseUser = FirebaseAuth.instance.currentUser;
DocumentReference docRef;
var response = await collection.where('uid', isEqualTo: firebaseUser.uid).get();
var batch = FirebaseFirestore.instance.batch();
response.docs.forEach((doc) {
docRef = collection.doc(doc.id);
batch.update(docRef, newDocumentBody);
});
batch.commit().then((a) {
print('updated all documents inside Collection');
});
}
Java 솔루션을 찾고 있는 사용자:
public boolean bulkUpdate() {
try {
// see https://firebase.google.com/docs/firestore/quotas#writes_and_transactions
int writeBatchLimit = 500;
int totalUpdates = 0;
while (totalUpdates % writeBatchLimit == 0) {
WriteBatch writeBatch = this.firestoreDB.batch();
// the query goes here
List<QueryDocumentSnapshot> documentsInBatch =
this.firestoreDB.collection("student")
.whereEqualTo("graduated", false)
.limit(writeBatchLimit)
.get()
.get()
.getDocuments();
if (documentsInBatch.isEmpty()) {
break;
}
// what I want to change goes here
documentsInBatch.forEach(
document -> writeBatch.update(document.getReference(), "graduated", true));
writeBatch.commit().get();
totalUpdates += documentsInBatch.size();
}
System.out.println("Number of updates: " + totalUpdates);
} catch (Exception e) {
return false;
}
return true;
}
Renato와 David의 답변과 배치 부분에 대한 비동기/대기 구문을 결합합니다.또한 약속이 실패할 경우를 대비하여 시도/어획물을 동봉합니다.
const updateAllFromCollection = async (collectionName) => {
const firebase = require('firebase-admin');
const collection = firebase.firestore().collection(collectionName);
const newDocumentBody = { message: 'hello world' };
try {
const response = await collection.where('message', '==', 'goodbye world').get();
const batch = firebase.firestore().batch();
response.docs.forEach((doc) => {
batch.update(doc.ref, newDocumentBody);
});
await batch.commit(); //Done
console.log(`updated all documents inside ${collectionName}`);
} catch (err) {
console.error(err);
}
return;
}
저는 몇 가지 답변이 마음에 들지만, 이것이 더 깨끗하다고 생각합니다.
import * as admin from "firebase-admin";
const db = admin.firestore();
const updates = { status: "pending" }
await db
.collection("COLLECTION_NAME")
.where("status", "==", "open")
.get()
.then((snap) => {
let batch = db.batch();
snap.docs.forEach((doc) => {
const ref = doc.ref;
batch.update(ref, updates);
});
return batch.commit();
});
일괄 업데이트와 문서의 "ref"를 사용합니다.
컬렉션 업데이트를 위해 이미 UID를 수집한 경우 다음 단계를 수행합니다.
if(uids.length) {
for(let i = 0; i < uids.length; i++) {
await (db.collection("collectionName")
.doc(uids[i]))
.update({"fieldName": false});
};
};
언급URL : https://stackoverflow.com/questions/48947499/can-firestore-update-multiple-documents-matching-a-condition-using-one-query
'code' 카테고리의 다른 글
| Oracle 오류: ORA-00905:키워드 누락 (0) | 2023.06.17 |
|---|---|
| VB.net 을 사용하여 Excel의 범위에 있는 셀에서 테두리를 제거하는 방법은 무엇입니까? (0) | 2023.06.17 |
| C에서 #error 지시어의 용도는 무엇입니까? (0) | 2023.06.17 |
| 인쇄 출력의 10진수(R) 수 제어 (0) | 2023.06.17 |
| 비탈출 매개변수를 폐쇄적으로 사용하면 탈출할 수 있습니다. (0) | 2023.06.17 |