MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Limpando arquivos órfãos do GridFS


Em primeiro lugar, vamos considerar o que GridFS na verdade é. E como iniciante, vamos ler a página de manual que é referenciada:

Então, com isso fora do caminho, e esse pode ser o seu caso de uso. Mas a lição a aprender aqui é que GridFS não é automaticamente o método "go-to" para armazenar arquivos.

O que aconteceu aqui no seu caso (e outros) é por causa da especificação do "nível do driver" que isso é (e o próprio MongoDB não não magic aqui), seus "arquivos" foram "divididos" em duas coleções. Uma coleção para a referência principal ao conteúdo e outra para os "pedaços" de dados.

Seu problema (e outros) é que você conseguiu deixar para trás os "pedaços" agora que a referência "principal" foi removida. Então, com um grande número, como se livrar dos órfãos.

Sua leitura atual diz "loop and compare", e como o MongoDB não faz junções , então realmente não há outra resposta. Mas há algumas coisas que podem ajudar.

Então, em vez de executar um enorme $nin , tente fazer algumas coisas diferentes para quebrar isso. Considere trabalhar na ordem inversa, por exemplo:
db.fs.chunks.aggregate([
    { "$group": { "_id": "$files_id" } },
    { "$limit": 5000 }
])

Então, o que você está fazendo é obter o distinto valores "files_id" (sendo as referências a fs.files ), de todas as entradas, para começar com 5.000 entradas. Então é claro que você está de volta ao loop, verificando fs.files para um _id correspondente . Se algo não for encontrado, remova os documentos que correspondem a "files_id" de seus "pedaços".

Mas eram apenas 5.000, então continue o último id encontrado nesse conjunto, porque agora você executará a mesma instrução agregada novamente, mas de maneira diferente:
db.fs.chunks.aggregate([
    { "$match": { "files_id": { "$gte": last_id } } },
    { "$group": { "_id": "$files_id" } },
    { "$limit": 5000 }
])

Então isso funciona porque o ObjectId os valores são monotonic ou "sempre crescente". Portanto, todos os novos entradas são sempre maiores que o último. Então você pode fazer um loop desses valores novamente e fazer as mesmas exclusões onde não foram encontrados.

Será que isso "levará para sempre". Bem sim . Você pode empregar db.eval() para isso, mas leia a documentação. Mas, no geral, esse é o preço que você paga pelo uso de dois coleções.

Volte para o começo. O GridFS a especificação é projetada dessa forma porque quer especificamente contornar a limitação de 16 MB. Mas se isso não sua limitação, então pergunte por que você está usando o GridFS em primeiro lugar.

O MongoDB não tem problema armazenar dados "binários" em qualquer elemento de um determinado documento BSON. Então você não precisa para usar GridFS apenas para armazenar arquivos. E se você tivesse feito isso, então todos das suas atualizações seriam completamente "atômicas", pois elas só agem em um documento em um coleta por vez.

Desde GridFS deliberadamente divide documentos em coleções, então, se você usá-lo, você vive com a dor. Portanto, use-o se precisar mas se você não , então apenas armazene o BinData como um campo normal, e esses problemas desaparecem.

Mas pelo menos você tem uma abordagem melhor do que carregar tudo na memória.