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

Pulizia dei file orfani da GridFS

Innanzitutto, prendiamoci il tempo per considerare cosa GridFS in realtà è. E come antipasto, leggiamo dalla pagina di manuale a cui si fa riferimento:

Quindi, con quello fuori mano, e questo potrebbe essere il tuo caso d'uso. Ma la lezione da imparare qui è che GridFS non è automaticamente il metodo "go-to" per la memorizzazione dei file.

Quello che è successo qui nel tuo caso (e in altri) è dovuto alle specifiche del "livello del conducente" che questo è (e MongoDB stesso non fa no magic here), i tuoi "file" sono stati "divisi" in due raccolte. Una raccolta per il riferimento principale al contenuto e l'altra per i "pezzi" di dati.

Il tuo problema (e altri) è che sei riuscito a lasciarti alle spalle i "pezzi" ora che il riferimento "principale" è stato rimosso. Quindi con un gran numero, come sbarazzarsi degli orfani.

La tua lettura attuale dice "loop and compare" e poiché MongoDB non esegue join , allora non c'è davvero altra risposta. Ma ci sono alcune cose che possono aiutare.

Quindi, piuttosto che eseguire un enorme $nin , prova a fare alcune cose diverse per interrompere questo. Considera di lavorare nell'ordine inverso, ad esempio:

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

Quindi quello che stai facendo lì è ottenere il distinto valori "files_id" (che sono i riferimenti a fs.files ), da tutte le voci, per iniziare con 5000 voci. Poi ovviamente sei tornato al loop, controllando fs.files per un _id corrispondente . Se qualcosa non viene trovato, rimuovere i documenti che corrispondono a "files_id" dai tuoi "pezzi".

Ma erano solo 5000, quindi continua l'ultimo id trovato in quel set, perché ora eseguirai di nuovo la stessa istruzione aggregata, ma in modo diverso:

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

Quindi funziona perché ObjectId i valori sono monotonic o "in continuo aumento". Quindi tutto nuovo le voci sono sempre maggiori di l'ultimo. Quindi puoi eseguire nuovamente un ciclo di quei valori e fare le stesse eliminazioni dove non sono stati trovati.

Questo "ci vorrà per sempre". Ebbene . potresti impiegare db.eval() per questo, ma leggi la documentazione. Ma nel complesso, questo è il prezzo che paghi per l'utilizzo di due collezioni.

Ritorno all'inizio. Il GridFS la specifica è progettata in questo modo perché lo vuole specificamente aggirare il limite di 16 MB. Ma se questo è non la tua limitazione, quindi chiedi perché stai usando GridFS in primo luogo.

MongoDB nessun problema memorizzazione di dati "binari" all'interno di qualsiasi elemento di un determinato documento BSON. Quindi non ti serve per utilizzare GridFS solo per memorizzare i file. E se lo avessi fatto, allora tutti dei tuoi aggiornamenti sarebbe completamente "atomico", in quanto agiscono solo su uno documento in uno raccolta alla volta.

Poiché GridFS deliberatamente divide i documenti tra le raccolte, quindi se lo usi, vivi con il dolore. Quindi usalo se ne hai bisogno esso, ma se lo fai non , quindi archivia i BinData come un campo normale, e questi problemi scompaiono.

Ma almeno hai un approccio migliore da adottare rispetto a caricare tutto in memoria.