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

Solução para localizar e modificar em massa no MongoDB


Como você mencionou, atualmente não há uma maneira limpa de fazer o que você deseja. A melhor abordagem neste momento para operações como a que você precisa é esta:
  1. O leitor seleciona X documentos com limite e classificação apropriados
  2. O leitor marca os documentos retornados por 1) com seu próprio ID de leitor exclusivo (e.g. update({_id:{$in:[<result set ids>]}, state:"available", $isolated:1}, {$set:{readerId:<your reader's ID>, state:"processing"}}, false, true) )
  3. O Reader seleciona todos os documentos marcados como em processamento e com seu próprio ID de leitor. Neste ponto, é garantido que você tenha acesso exclusivo ao conjunto de documentos resultante.
  4. Ofereça o conjunto de resultados de 3) para seu processamento.

Observe que isso funciona mesmo em situações altamente simultâneas, pois um leitor nunca pode reservar documentos ainda não reservados por outro leitor (observe que a etapa 2 só pode reservar documentos atualmente disponíveis e as gravações são atômicas). Eu adicionaria um carimbo de data/hora com o tempo de reserva também se você quiser poder expirar reservas (por exemplo, para cenários em que os leitores podem falhar/falhar).

EDIT:Mais detalhes:

Todas as operações de gravação podem ocasionalmente resultar em operações pendentes se a gravação demorar um tempo relativamente longo. Isso significa que a etapa 2) pode não ver todos os documentos marcados pela etapa 1), a menos que você execute as seguintes etapas:
  • Use um valor "w" apropriado (escrever preocupação), significando 1 ou superior. Isso garantirá que a conexão na qual a operação de gravação é invocada aguardará a conclusão, independentemente de sua produção.
  • Certifique-se de fazer a leitura na etapa 2 na mesma conexão (relevante apenas para conjuntos de réplicas com leituras habilitadas para slaveOk) ou encadeamento para garantir que sejam sequenciais. O primeiro pode ser feito na maioria dos drivers com os métodos "requestStart" e "requestDone" ou similares (documentação Java aqui ).
    • Adicione o sinalizador $isolated às suas várias atualizações para garantir que ele não possa ser intercalado com outras operações de gravação.

Veja também comentários para discussão sobre atomicidade/isolamento. Eu assumi incorretamente que as múltiplas atualizações foram isoladas. Eles não são, ou pelo menos não por padrão.