sql >> Database teknologi >  >> NoSQL >> MongoDB

Rensning af forældreløse filer ud af GridFS

Lad os først tage os tid til at overveje, hvad GridFS faktisk er. Og som en starter, lad os læse fra den manualside, der henvises til:

Så med det af vejen, og det kan godt være din use case. Men lektien at lære her er, at GridFS er ikke automatisk "gå-til"-metoden til lagring af filer.

Det, der er sket her i dit tilfælde (og andre) er på grund af specifikationen af "førerniveau". at dette er (og MongoDB selv gør nej magi her), Dine "filer" er blevet "delt" på tværs af to samlinger. Den ene samling for hovedreferencen til indholdet, og den anden for "klumperne" af data.

Dit problem (og andre) er, at du har formået at efterlade "klumperne", nu hvor "hoved" referencen er blevet fjernet. Så med et stort antal, hvordan man slipper af med de forældreløse børn.

Din nuværende læsning siger "loop og sammenlign", og siden MongoDB ikke gør joins , så er der virkelig ikke noget andet svar. Men der er nogle ting, der kan hjælpe.

Så i stedet for at køre en enorm $nin , prøv at gøre et par forskellige ting for at bryde dette op. Overvej at arbejde i omvendt rækkefølge, for eksempel:

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

Så det, du gør der, er at få det distinkte "files_id"-værdier (der er referencerne til fs.files ), fra alle poster, for 5000 af dine poster til at starte med. Så er du selvfølgelig tilbage til loopingen, og tjekker fs.files for et matchende _id . Hvis noget ikke findes, så fjern de dokumenter, der matcher "files_id" fra dine "chunks".

Men det var kun 5000, så behold den sidste id fundet i det sæt, for nu skal du køre den samme samlede sætning igen, men anderledes:

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

det virker fordi ObjectId værdier er monotone eller "stadig stigende". Så alt nyt poster er altid større end den sidste. Så kan du gå en løkke over disse værdier igen og gøre de samme sletninger, hvor de ikke findes.

Vil dette "tage evigt". Nå ja . Du måske ansæt db.eval() for dette, men læs dokumentationen. Men overordnet set er dette prisen, du betaler for at bruge to samlinger.

Tilbage til starten. GridFS spec er designet på denne måde, fordi den specifikt ønsker at arbejde omkring 16 MB begrænsningen. Men hvis det ikke er det din begrænsning, og spørg derefter hvorfor du bruger GridFS i første omgang.

MongoDB har ingen problemer lagring af "binære" data i ethvert element i et givet BSON-dokument. Så du behøver ikke at bruge GridFS bare for at gemme filer. Og hvis du havde gjort det, så alle af dine opdateringer ville være fuldstændig "atomiske", da de kun virker på én dokument i én indsamling ad gangen.

Siden GridFS bevidst deler dokumenter på tværs af samlinger, så hvis du bruger det, så lever du med smerten. Så brug det, hvis du bruger det, men hvis du ikke gør det , og gem derefter BinData som et normalt felt, og disse problemer forsvinder.

Men du har i det mindste en bedre tilgang end at indlæse alt i hukommelsen.



  1. Hvorfor får jeg mongoose.connect er ikke en funktion, når jeg prøver at oprette forbindelse til mongoose?

  2. Tuning Java Garbage Collection til HBase

  3. MongoDB $elemMatch $in

  4. Hvordan søger du efter nøgler med en værdi? Få for eksempel alle NØGLER, hvor værdien er en eller anden værdi