换句话说,我试图在SQL中找出与此相当的Firestore:
UPDATE table SET field = 'foo' WHERE <condition>`
是的,我问的是如何update multiple documents,at once,但与链接的问题不同,我特意询问如何一次性完成此操作,没有阅读任何内容内存,因为当你想要的只是在符合条件的所有文件上设置一个标志时,不需要这样做。
db.collection('table')
.where(...condition...)
.update({
field: 'foo',
});
是我期望的工作,CollectionReference没有.update
方法。
Transactions and Batched Writes文档提到了事务和批量写入。交易结束是因为&#34;交易包含任意数量的 get()操作,后跟任意数量的写操作&#34; Batched writes也不是解决方案,因为它们逐个文档地工作。
使用MongoDB,这将是
db.table.update(
{ /* where clause */ },
{ $set: { field: 'foo' } }
)
那么,Firestore可以用一个查询更新多个文档,SQL数据库或MongoDB的工作方式,即不需要为每个文档往返客户端吗?如果没有,如何有效地完成这项工作?
答案 0 :(得分:12)
在Cloud Firestore中更新文档需要知道其ID。 Cloud Firestore不支持SQL的更新查询等效项。
您将始终分两步执行此操作:
请注意,您只需要步骤1中的文档ID。因此,您可以运行仅返回ID的查询。这在客户端SDK中是不可能的,但可以通过REST API和Admin SDK完成,如下所示:How to get a list of keys in Firestore?
答案 1 :(得分:2)
最简单的方法是这样
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 })
})
}
})
答案 2 :(得分:1)
如果有人正在寻找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;
}
答案 3 :(得分:0)
弗兰克的答案实际上是一个很好的答案,确实可以解决问题。
但是对于那些着急的人来说,此片段可能会帮助您:
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
。
也不要忘记使用集合名称来调用函数。
答案 4 :(得分:0)
对于Dart / Flutter用户(由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');
});
}
答案 5 :(得分:0)
结合 Renato 和 David 的答案,以及批处理部分的 async/await 语法。还包括一个 try/catch 以防任何承诺失败:
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;
}