Este grupo de especialistas pasados muchos días de investigación y de recopilar de información, encontramos los datos necesarios, queremos que resulte de gran utilidad para tu trabajo.
Solución:
La RTDB puede hacer esto porque cada base de datos es local para una sola región. Para proporcionar una vista serializada, cuando llama remove()
la base de datos detiene el resto del trabajo hasta que se completa la eliminación.
Este comportamiento ha sido la causa de varias interrupciones aparentes: si un remove()
la llamada tiene que eliminar grandes cantidades de datos, todas las demás actividades se bloquean efectivamente hasta que se completan. Como resultado, incluso para los usuarios de RTDB que desean eliminar grandes cantidades de datos, recomendamos buscar y eliminar documentos en grupos de forma recursiva (CLI, node.js).
Firestore, por otro lado, se basa en una infraestructura de almacenamiento de estilo más tradicional de Google donde diferentes rangos de keys se asignan dinámicamente a diferentes servidores (el almacenamiento no está realmente respaldado por BigTable, pero se aplican los mismos principios). Esto significa que la eliminación de datos ya no es necesariamente una acción de una sola región y se vuelve muy costoso hacer que la eliminación parezca transaccional. Las transacciones de Firestore actualmente están limitadas a 100 participantes y esto significa que cualquier eliminación masiva transaccional no trivial es imposible.
Estamos investigando la mejor manera de mostrar una API que realiza una eliminación masiva sin prometer un comportamiento transaccional. Es sencillo imaginar cómo hacer esto desde un cliente móvil, pero como ha observado, esto no sería eficiente si todo lo que hiciéramos fuera incrustar el bucle y la eliminación por lotes por usted. Tampoco queremos convertir a los clientes REST en ciudadanos de segunda clase.
Firestore es un producto nuevo y aún quedan muchas cosas por hacer. Desafortunadamente, esto simplemente no ha hecho el corte. Si bien esto es algo que esperamos abordar eventualmente, no puedo proporcionar ningún cronograma sobre cuándo sería.
Mientras tanto, la consola y la línea de comandos de firebase proporcionan un medio no transaccional para hacer esto, por ejemplo, para la automatización de pruebas.
¡Gracias por su comprensión y gracias por probar Firestore!
Estaba felizmente refactorizando mi aplicación para Firestore desde Realtime Database, disfrutando del código más corto y la sintaxis más simple, ¡hasta que refactoricé las funciones delete()! Para eliminar un documento con subcolecciones:
- Crear un array de promesas
get()
una subcolección, que no tiene más subcolecciones.- Iterar a través de un
forEach()
función para leer cada documento en la subcolección. - Elimine cada documento y presione el comando Eliminar en el array de promesas
- Vaya a la siguiente subcolección y repita esto.
- Utilizar
Promise.all(arrayOfPromises)
esperar hasta que se hayan eliminado todas las subcolecciones. - A continuación, elimine el documento de nivel superior.
Con múltiples capas de colecciones y documentos, querrá convertir eso en una función, luego llamarlo desde otra función para obtener la siguiente capa superior, etc.
Puedes ver esto en la consola. Para eliminar manualmente colecciones y documentos, elimine el documento que se encuentra más a la derecha, luego elimine la colección que se encuentra más a la derecha y así sucesivamente trabajando hacia la izquierda.
Aquí está mi código, en AngularJS. Solo funciona si la colección de nivel superior no se eliminó antes que las subcolecciones.
$scope.deleteClip = function(docId)
if (docId === undefined)
docId = $scope.movieOrTvShow + '_' + $scope.clipInMovieModel;
$scope.languageVideos = longLanguageFactory.toController($scope.language) + 'Videos';
var promises = [];
firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).collection('SentenceTranslations').get()
.then(function(translations)
translations.forEach(function(doc)
console.log(doc.id);
promises.push(firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).collection('SentenceTranslations').doc(doc.id).delete());
);
);
firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).collection('SentenceExplanations').get()
.then(function(explanations)
explanations.forEach(function(doc)
console.log(doc.id);
promises.push(firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).collection('SentenceExplanations').doc(doc.id).delete());
);
);
Promise.all(promises).then(function()
console.log("All subcollections deleted.");
firebase.firestore().collection($scope.languageVideos).doc($scope.movieOrTvShow).collection('Video Clips').doc(docId).delete()
.then(function()
console.log("Collection deleted.");
$scope.clipInMovieModel = null;
$scope.$apply();
)
.catch(function(error)
console.log("Remove failed: " + error.message);
);
)
.catch(function(error)
console.log("Error deleting subcollections: " + error);
);
;
Todo eso habría sido una línea en Realtime Database.
Esta es la forma más rápida de eliminar todos los documentos de una colección: mezcle entre el bucle de colección de eliminación de python y el método por lotes de python
def delete_collection(coll_ref, batch_size, counter):
batch = db.batch()
init_counter=counter
docs = coll_ref.limit(500).get()
deleted = 0
for doc in docs:
batch.delete(doc.reference)
deleted = deleted + 1
if deleted >= batch_size:
new_counter= init_counter + deleted
batch.commit()
print("potentially deleted: " + str(new_counter))
return delete_collection(coll_ref, batch_size, new_counter)
batch.commit()
delete_collection(db.collection(u'productsNew'), 500, 0)
esto elimina todos los documentos de la colección “productNew” en bloques de 500, que actualmente es el número máximo de documentos que se pueden pasar a una confirmación. Consulte Cuotas de transacción y escritura de Firebase.
Puede volverse más sofisticado y manejar también los errores de API, pero esto funciona bien para mí.