MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Verwaiste Dateien aus GridFS entfernen

Nehmen wir uns zunächst die Zeit, darüber nachzudenken, was GridFS ist eigentlich ist. Und als Einstieg lesen wir die Handbuchseite, auf die verwiesen wird:

Also damit aus dem Weg, und das könnte durchaus Ihr Anwendungsfall sein. Aber die Lektion, die Sie hier lernen sollten, ist, dass GridFS nicht automatisch die "go-to"-Methode zum Speichern von Dateien.

Was hier in Ihrem Fall (und anderen) passiert ist, liegt an der Spezifikation des "Fahrerniveaus". dass dies der Fall ist (und MongoDB selbst tut nein Magie hier), Ihre "Dateien" wurden auf zwei Sammlungen "aufgeteilt". Eine Sammlung für den Hauptbezug zum Inhalt und die andere für die "Blöcke" von Daten.

Ihr Problem (und andere) ist, dass Sie es geschafft haben, die "Chunks" zurückzulassen, nachdem die "Haupt" -Referenz entfernt wurde. Also bei einer großen Zahl, wie man die Waisen loswird.

Ihre aktuelle Lektüre sagt "Schleife und Vergleich", und da MongoDB keine Joins durchführt , dann gibt es wirklich keine andere Antwort. Aber es gibt einige Dinge, die helfen können.

Anstatt also einen riesigen $nin auszuführen , versuchen Sie, ein paar verschiedene Dinge zu tun, um dies zu unterbrechen. Erwägen Sie, in umgekehrter Reihenfolge zu arbeiten, zum Beispiel:

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

Was Sie dort also tun, ist, das Eindeutige zu erhalten „files_id“-Werte (die Verweise auf fs.files sind ), aus allen Einsendungen, für zunächst 5000 Ihrer Einsendungen. Dann sind Sie natürlich wieder bei der Schleife und überprüfen fs.files für eine passende _id . Wenn etwas nicht gefunden wird, dann entfernen die Dokumente, die mit "files_id" aus Ihren "Chunks" übereinstimmen.

Aber das waren nur 5000, also behalten die letzte id in diesem Satz gefunden, denn jetzt werden Sie dieselbe Aggregatanweisung noch einmal ausführen, aber anders:

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

Also das funktioniert weil die ObjectId Werte sind monoton oder "immer mehr". Also alles neu Einträge sind immer größer als das Letzte. Dann können Sie diese Werte erneut durchlaufen und die gleichen Löschungen durchführen, wo sie nicht gefunden wurden.

Wird das "ewig dauern". Nun ja . Du vielleicht Verwenden Sie db.eval() dafür aber lesen die Dokumentation. Aber insgesamt ist dies der Preis, den Sie für die Verwendung von zwei zahlen Sammlungen.

Zurück zum Anfang. Das GridFS spec ist entworfen auf diese Weise, weil es ausdrücklich will Umgehen Sie die 16-MB-Beschränkung. Aber wenn das nicht ist Ihre Einschränkung, dann hinterfragen Sie warum Sie verwenden GridFS an erster Stelle.

MongoDB hat kein Problem Speichern von "binären" Daten innerhalb eines beliebigen Elements eines bestimmten BSON-Dokuments. Sie brauchen also nicht um GridFS zu verwenden nur um Dateien zu speichern. Und wenn ja, dann alle Ihrer Updates wäre komplett "atomar", da sie nur auf eine wirken Dokument in einem Sammlung zu einem Zeitpunkt.

Seit GridFS absichtlich teilt Dokumente auf Sammlungen auf, und wenn Sie es verwenden, leben Sie mit dem Schmerz. Verwenden Sie es also, wenn Sie es brauchen es, aber wenn Sie nicht tun , speichern Sie dann einfach die BinData als normales Feld, und diese Probleme verschwinden.

Aber zumindest haben Sie einen besseren Ansatz, als alles in den Speicher zu laden.