sql >> Databáze >  >> NoSQL >> MongoDB

Čištění osiřelých souborů z GridFS

Za prvé, pojďme zvážit, co GridFS ve skutečnosti je. A pro začátek si přečtěte z manuálové stránky, na kterou se odkazuje:

Takže s tím z cesty, a to může být váš případ použití. Ale poučení, které je třeba se zde naučit, je, že GridFS není automaticky metoda "go-to" pro ukládání souborů.

To, co se stalo ve vašem případě (a dalších), je způsobeno specifikací "úrovně řidiče" že to tak je (a samotný MongoDB to ne dělá magic here), Vaše „soubory“ byly „rozděleny“ do dvou sbírek. Jedna kolekce pro hlavní odkaz na obsah a druhá pro „kusy“ dat.

Váš problém (a další) je, že se vám podařilo zanechat „kousky“ nyní, když byla odstraněna „hlavní“ reference. Takže s velkým počtem, jak se zbavit sirotků.

Vaše aktuální čtení říká „otočit a porovnat“, a protože MongoDB neprovádí připojení , pak opravdu není jiná odpověď. Ale existují věci, které mohou pomoci.

Takže raději než spustit obrovský $nin , zkuste udělat několik různých věcí, abyste to rozbili. Zvažte práci v opačném pořadí, například:

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

Takže to, co tam děláte, se rozlišuje hodnoty "files_id" (což jsou odkazy na fs.files ), ze všech záznamů, pro začátek 5 000 vašich záznamů. Pak se samozřejmě vrátíte do smyčky a zkontrolujete fs.files pro odpovídající _id . Pokud něco není nalezeno, odstraňte dokumenty odpovídající "files_id" z vašich "kusů".

Ale to bylo jen 5000, takže nechte poslední id nalezené v této sadě, protože nyní spustíte stejný souhrnný příkaz znovu, ale jinak:

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

Takže toto funguje protože ObjectId hodnoty jsou monotónní nebo „stále rostoucí“. Takže vše nové položky jsou vždy větší než poslední. Potom můžete tyto hodnoty znovu zacyklit a provést stejné mazání tam, kde nebyly nalezeny.

Bude to „trvá věčnost“. Tedy ano . Možná zaměstnávejte db.eval() k tomu, ale čtěte dokumentaci. Celkově je to však cena, kterou zaplatíte za použití dvou sbírky.

Zpátky na začátek. GridFS spec je navrženo tímto způsobem, protože to konkrétně chce obejít omezení 16 MB. Ale pokud to není vaše omezení, pak se zeptejte proč používáte GridFS na prvním místě.

MongoDB nemá žádný problém ukládání "binárních" dat v rámci libovolného prvku daného BSON dokumentu. Takže nepotřebujete použít GridFS jen pro ukládání souborů. A pokud jste tak učinili, pak vše z vašich aktualizací by byly zcela „atomické“, protože fungují pouze na jednu dokument v jednom sběru najednou.

Protože GridFS úmyslně rozděluje dokumenty do sbírek, pak pokud to používáte, žijete s bolestí. Takže jej použijte, pokud potřebujete to, ale pokud to neděláte , pak stačí uložit BinData jako normální pole a tyto problémy zmizí.

Ale alespoň máte lepší přístup než načítání všeho do paměti.



  1. Jak porovnat 2 pole v Spring Data MongoDB pomocí objektu dotazu

  2. MongoDB:nelze upsert, pokud objekt dotazu a objekt aktualizace obsahují stejnou vlastnost, 'Nelze použít modifikátor $addToSet na non-array'

  3. Jak vyčistím zaseknuté/zastarané pracovníky Resque?

  4. Solr Mongo/DocDB Delta Import Query nefunguje