sql >> Database >  >> NoSQL >> MongoDB

Verweesde bestanden opschonen uit GridFS

Laten we eerst de tijd nemen om te overwegen wat GridFS eigenlijk is. En als een starter, laten we lezen van de man-pagina waarnaar wordt verwezen:

Dus met dat uit de weg, en dat zou wel eens jouw use case kunnen zijn. Maar de les die we hier moeten leren, is dat GridFS is niet automatisch de "go-to"-methode voor het opslaan van bestanden.

Wat hier in jouw geval (en anderen) is gebeurd, is vanwege de specificatie dat dit zo is (en MongoDB zelf doet nee magic here), uw "bestanden" zijn "gesplitst" over twee collecties. Eén verzameling voor de belangrijkste verwijzing naar de inhoud en de andere voor de "brokken" gegevens.

Uw probleem (en anderen) is dat u erin geslaagd bent de "brokken" achter te laten nu de "hoofd"-referentie is verwijderd. Dus met een groot aantal, hoe van de wezen af ​​te komen.

Uw huidige waarde zegt "loop en vergelijk", en aangezien MongoDB geen joins doet , dan is er eigenlijk geen ander antwoord. Maar er zijn enkele dingen die kunnen helpen.

Dus in plaats van een enorme $nin , probeer een paar verschillende dingen te doen om dit te doorbreken. Overweeg om in omgekeerde volgorde te werken, bijvoorbeeld:

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

Dus wat je daar doet, is het onderscheiden . krijgen "files_id" waarden (zijnde de verwijzingen naar fs.files ), van alle inzendingen, voor 5000 van uw inzendingen om mee te beginnen. Dan ben je natuurlijk weer terug bij de looping, het controleren van fs.files voor een overeenkomende _id . Als iets niet wordt gevonden, verwijderen de documenten die overeenkomen met "files_id" uit uw "chunks".

Maar dat waren er maar 5000, dus blijf de laatste id gevonden in die set, want nu ga je hetzelfde geaggregeerde statement opnieuw uitvoeren, maar anders:

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

Dus dit werkt omdat de ObjectId waarden zijn monotoon of "steeds toenemend". Dus allemaal nieuw inzendingen zijn altijd groter dan de laatste. Dan kun je die waarden opnieuw herhalen en dezelfde verwijderingen doen waar ze niet zijn gevonden.

Zal dit "voor altijd duren". Nou ja . Je misschien gebruik db.eval() hiervoor, maar lees de documentatie. Maar over het algemeen is dit de prijs die u betaalt voor het gebruik van twee collecties.

Terug naar het begin. De GridFS spec is ontworpen op deze manier omdat het specifiek wil werk rond de 16 MB beperking. Maar als dat niet is uw beperking, vraag dan waarom je gebruikt GridFS in de eerste plaats.

MongoDB heeft geen probleem het opslaan van "binaire" gegevens binnen elk element van een bepaald BSON-document. Dus je niet nodig om GridFS te gebruiken alleen om bestanden op te slaan. En als je dat had gedaan, dan allemaal van uw updates zou volledig "atomair" zijn, omdat ze slechts op één . werken document in één verzameling tegelijk.

Sinds GridFS opzettelijk verdeelt documenten over collecties, en als je het gebruikt, leef je met de pijn. Dus gebruik het als je nodig het, maar als u niet , sla dan gewoon de BinData . op als een normaal veld, en deze problemen verdwijnen.

Maar je hebt in ieder geval een betere aanpak dan alles in het geheugen te laden.



  1. Hoe een Mongodb-schema dynamisch te maken met nodejs

  2. PHP kan dynamische bibliotheek niet laden (mongo.so)

  3. Spring data mongo gebruik OR in Query

  4. Kan geen verbinding maken met MongoDB-server op Google Compute Engine vanaf tweede VM-instantie