Låt oss först ta oss tid att överväga vad GridFS faktiskt är. Och till att börja med, låt oss läsa från manualsidan som det refereras till:
Så med det ur vägen, och det kan mycket väl vara ditt användningsfall. Men läxan att lära här är att GridFS är inte automatiskt "gå till"-metoden för att lagra filer.
Det som har hänt här i ditt fall (och andra) är på grund av specifikationen för "förarnivå". att detta är (och MongoDB själv gör nej magi här), Dina "filer" har "delats" över två samlingar. En samling för huvudreferensen till innehållet och den andra för "bitarna" av data.
Ditt problem (och andra), är att du har lyckats lämna kvar "bitarna" nu när "huvudsakliga" referensen har tagits bort. Så med ett stort antal, hur man blir av med föräldralösa barn.
Din nuvarande läsning säger "loop och jämför", och eftersom MongoDB inte gör joins , då finns det verkligen inget annat svar. Men det finns några saker som kan hjälpa.
Så istället för att köra en enorm $nin
, försök att göra några olika saker för att bryta det här. Överväg att arbeta i omvänd ordning, till exempel:
db.fs.chunks.aggregate([
{ "$group": { "_id": "$files_id" } },
{ "$limit": 5000 }
])
Så vad du gör där är att få det distinkt "files_id"-värden (som är referenserna till fs.files
), från alla poster, för 5000 av dina poster till att börja med. Sedan är du naturligtvis tillbaka till loopingen, kollar fs.files
för ett matchande _id
. Om något inte hittas ta bort dokumenten som matchar "files_id" från dina "bitar".
Men det var bara 5000, så behåll det sista id som finns i den uppsättningen, för nu kommer du att köra samma sammanställda uttalande igen, men annorlunda:
db.fs.chunks.aggregate([
{ "$match": { "files_id": { "$gte": last_id } } },
{ "$group": { "_id": "$files_id" } },
{ "$limit": 5000 }
])
Så det här fungerar eftersom ObjectId
värdena är monotona
eller "alltid ökande". Så allt nytt poster är alltid större än den sista. Sedan kan du gå en slinga på dessa värden igen och göra samma raderingar där de inte hittas.
Kommer detta "ta för evigt". Nåväl ja . Du kanske använd db.eval()
för detta, men läs dokumentationen. Men totalt sett är detta priset du betalar för att använda två samlingar.
Tillbaka till början. GridFS spec är designad på detta sätt eftersom den specifikt vill arbeta runt begränsningen på 16 MB. Men om det inte är det din begränsning, fråga sedan varför du använder GridFS i första hand.
MongoDB har inga problem lagra "binär" data inom valfritt element i ett givet BSON-dokument. Så du behöver inte att använda GridFS bara för att lagra filer. Och om du hade gjort det, då alla av dina uppdateringar skulle vara helt "atomära", eftersom de bara verkar på en dokument i ett samling åt gången.
Sedan GridFS
medvetet delar upp dokument över samlingar, sedan om du använder det, då lever du med smärtan. Så använd den om du behöver det, men om du inte gör det , sedan är det bara att lagra BinData
som ett normalt fält, och dessa problem försvinner.
Men du har åtminstone ett bättre tillvägagångssätt än att ladda allt i minnet.