sql >> Base de Datos >  >> NoSQL >> MongoDB

Limpieza de archivos huérfanos de GridFS

En primer lugar, tomemos el tiempo para considerar qué GridFS en realidad es. Y para empezar, leamos la página del manual a la que se hace referencia:

Entonces, con eso fuera del camino, y ese bien puede ser su caso de uso. Pero la lección a aprender aquí es que GridFS no es automáticamente el método "ir a" para almacenar archivos.

Lo que ha sucedido aquí en su caso (y en otros) se debe a la especificación de "nivel de controlador" que esto es (y MongoDB en sí mismo no magia aquí), sus "archivos" se han "dividido" en dos colecciones. Una colección para la referencia principal al contenido y la otra para los "fragmentos" de datos.

Su problema (y otros), es que ha logrado dejar atrás los "trozos" ahora que se ha eliminado la referencia "principal". Entonces, con un gran número, cómo deshacerse de los huérfanos.

Su lectura actual dice "bucle y compare", y dado que MongoDB no hace uniones , entonces realmente no hay otra respuesta. Pero hay algunas cosas que pueden ayudar.

Entonces, en lugar de ejecutar un enorme $nin , intente hacer algunas cosas diferentes para romper esto. Considere trabajar en el orden inverso, por ejemplo:

db.fs.chunks.aggregate([
    { "$group": { "_id": "$files_id" } },
    { "$limit": 5000 }
])

Entonces, lo que estás haciendo allí es obtener el distinto valores "files_id" (siendo las referencias a fs.files ), de todas las entradas, para empezar con 5000 de sus entradas. Luego, por supuesto, vuelve al bucle, comprobando fs.files para un _id coincidente . Si no se encuentra algo, eliminar los documentos que coinciden con "files_id" de sus "trozos".

Pero eso fue solo 5000, así que mantén la última id encontrado en ese conjunto, porque ahora va a ejecutar la misma declaración agregada nuevamente, pero de manera diferente:

db.fs.chunks.aggregate([
    { "$match": { "files_id": { "$gte": last_id } } },
    { "$group": { "_id": "$files_id" } },
    { "$limit": 5000 }
])

Así que esto funciona porque el ObjectId los valores son monotonic o "cada vez mayor". Así que todo nuevo las entradas siempre son mayores que el último. Luego puede volver a repetir esos valores y hacer las mismas eliminaciones donde no se encuentran.

¿Esto "tomará para siempre"? Pues . Usted podría emplear db.eval() para esto, pero leer la documentación. Pero, en general, este es el precio que paga por usar dos colecciones.

De vuelta al principio. El GridFS la especificación está diseñada de esta manera porque específicamente quiere evite la limitación de 16 MB. Pero si eso es no tu limitación, entonces pregúntate por qué está utilizando GridFS en primer lugar.

MongoDB tiene ningún problema almacenar datos "binarios" dentro de cualquier elemento de un documento BSON dado. Entonces no necesitas para usar GridFS solo para almacenar archivos. Y si lo hubieras hecho, entonces todas de tus actualizaciones serían completamente "atómicas", ya que solo actúan sobre una documento en uno colección a la vez.

Desde GridFS deliberadamente divide documentos en colecciones, luego, si lo usa, entonces vive con el dolor. Así que úsalo si necesitas pero si no , luego simplemente almacene el BinData como un campo normal, y estos problemas desaparecen.

Pero al menos tiene un mejor enfoque que tomar que cargar todo en la memoria.