Вы можете использовать облачную функцию: например, ниже вы найдете код облачной функции, который вы бы вызвали, создав документ в коллекции с именем batchUpdateTrigger
(обратите внимание, что это просто способ вызвать облачную функцию. Для этого вы вполне могли бы использовать облачную функцию HTTPS.
В этой облачной функции мы берем все документы из коллекции с именем collection
и добавляем в каждое из них новое поле с текущей датой./ время (ServerValue.TIMESTAMP
).Мы используем Promise.all()
для параллельного выполнения всей асинхронной работы по обновлению.Не забудьте добавить доступ на запись в коллекцию batchUpdateTrigger
и удалить облачную функцию после ее запуска.
exports.batchUpdate = functions.firestore
.document('batchUpdateTrigger/{triggerId}')
.onCreate((snap, context) => {
var collecRef = db.collection('collection');
return admin.collecRef.get()
.then(snapshot => {
const ts = admin.database.ServerValue.TIMESTAMP;
var promises = [];
snapshot.forEach(doc => {
const ref = doc.ref;
promises.push(
ref.update({
lastUpdate: ts
});
);
});
return Promise.all(promises);
});
});
Одна из проблем, с которой вы можете здесь столкнуться, состоит в том, что вы достигаете тайм-аута облачной функции.,Время ожидания по умолчанию составляет 60 секунд, но вы можете увеличить его в консоли Google Cloud (https://console.cloud.google.com/functions/list?project=xxxxxxx)
. Другой подход, как вы сказали, заключается в использовании пакетной записи .
В этом случае облачная функция будет выглядеть следующим образом:
exports.batchUpdate = functions.firestore
.document('batchUpdateTrigger/{triggerId}')
.onCreate((snap, context) => {
var collecRef = db.collection('collection');
return admin.collecRef.get()
.then(snapshot => {
const ts = admin.database.ServerValue.TIMESTAMP;
let batch = db.batch();
snapshot.forEach(doc => {
const ref = doc.ref;
batch.update(ref, {
lastUpdate: ts
});
});
return batch.commit();
});
});
Однако вам потребуется в коде управлять максимальным пределом в 500 операций в пакете .
Ниже приведен возможный простой подход (т. Е. Не очень сложный ...). Поскольку вы будете устанавливать значения по умолчанию только один раз, и у вас будет всего несколько сотен документов наМы можем считать это приемлемым! Следующая облачная функция будет обрабатывать документы с партией от 500. Поэтому вам, возможно, придется вручную повторно запускать ее, пока не будут обработаны все документы.
exports.batchUpdate = functions.firestore
.document('batchUpdateTrigger/{triggerId}')
.onCreate((snap, context) => {
var collecRef = db.collection('collection');
return admin.collecRef.get()
.then(snapshot => {
const docRefsArray = [];
snapshot.forEach(doc => {
if (doc.data().lastUpdate == null) {
//We need to "treat" this doc
docRefsArray.push(doc.ref);
)
});
console.log("Nbr of doc to treat: " + docRefsArray.length); //When the output is 0 you are done, i.e. all the docs are treated
if (docRefsArray.length > 0) {
const ts = admin.database.ServerValue.TIMESTAMP;
let batch = db.batch();
if (docRefsArray.length < 500) {
//We can "treat" all the documents in the QuerySnapshot
docRefsArray.forEach(ref => {
batch.update(ref, {
lastUpdate: ts
});
});
} else {
//We need to "treat" only 500 documents
for (let i = 0; i < 500; i++) {
batch.update(docRefsArray[i], {
lastUpdate: ts
});
}
return batch.commit();
} else {
return null;
}
});
});
Преимущество этого последнегоТехника заключается в том, что если вы столкнулись с некоторыми проблемами тайм-аута облачной функции, вы можете уменьшить размер пакета.