Qual é a diferença entre findAndModify e atualização no MongoDB?

175

Estou um pouco confuso com o findAndModifymétodo no MongoDB. Qual é a vantagem disso sobre o updatemétodo? Para mim, parece que ele retorna o item primeiro e depois o atualiza. Mas por que preciso devolver o item primeiro? Eu li o MongoDB: o guia definitivo e ele diz que é útil para manipular filas e executar outras operações que precisam de atomicidade no estilo get-and-set. Mas não entendi como isso é alcançado. Alguém pode me explicar isso?

chaonextdoor
fonte

Respostas:

153

Se você buscar um item e atualizá-lo, pode haver uma atualização por outro thread entre essas duas etapas. Se você atualizar um item primeiro e depois buscá-lo, pode haver outra atualização intermediária e você receberá um item diferente do que foi atualizado.

Fazer isso "atomicamente" significa que você terá a garantia de que está recebendo exatamente o mesmo item que está atualizando - ou seja, nenhuma outra operação pode acontecer no meio.

Asya Kamsky
fonte
6
Eu ainda estou um pouco confuso. Como findAndModifygarante que não há outra operação de atualização interferindo nela?
Chaonextdoor
78
@chaonextdoor findAndModify adquire um bloqueio no banco de dados quando inicia a operação, para que nenhuma outra operação possa processar enquanto estiver em execução. Quando termina a operação, libera a trava.
Lycha 28/05
4
findAndModify não obtém realmente um bloqueio até a parte de modificação da solicitação. Portanto, é possível que vários processos possam atualizar o mesmo registro.
Mark Unsworth
5
O @MarkUnsworth abre um caso de suporte com 10gen - se houver um erro no bloqueio do findAndModify, posso garantir que os engenheiros queiram corrigi-lo o mais rápido possível. Se esse fosse o caso, veríamos muitas pessoas relatando esse comportamento, mas findAndModify funciona como projetado para praticamente todo mundo que o está usando - casos em que parecia que não se tratava de erros de lógica ou implementação no lado do cliente , mas é claro que em softwares complexos sempre pode haver um bug.
Asya Kamsky
4
@AsyaKamsky Eu estava pensando em discutir com você, mas depois percebi que você está correto, então agora estou pensando em me desculpar. Desculpe!
funkyeah 18/09/2015
54

findAndModify retorna o documento, a atualização não.

Se eu entendi Dwight Merriman (um dos autores originais do mongoDB) corretamente, o uso de update para modificar um único documento, ou seja ("multi": false} também é atômico. Atualmente, também deve ser mais rápido do que fazer a atualização equivalente usando findAndModify.

Yaniv
fonte
31

Dos documentos do MongoDB (ênfase adicionada):

  • Por padrão, as duas operações modificam um único documento. No entanto, o método update () com sua opção múltipla pode modificar mais de um documento .

  • Se vários documentos corresponderem aos critérios de atualização, para findAndModify (), você poderá especificar uma classificação para fornecer alguma medida de controle sobre qual documento atualizar. Com o comportamento padrão do método update (), você não pode especificar qual documento único atualizar quando vários documentos corresponderem.

  • Por padrão, o método findAndModify () retorna a versão pré-modificada do documento . Para obter o documento atualizado, use a nova opção. O método update () retorna um objeto WriteResult que contém o status da operação. Para retornar o documento atualizado, use o método find (). No entanto, outras atualizações podem ter modificado o documento entre a atualização e a recuperação do documento. Além disso, se a atualização modificou apenas um único documento, mas vários documentos corresponderam, você precisará usar uma lógica adicional para identificar o documento atualizado.

  • Antes do MongoDB 3.2, você não pode especificar uma preocupação de gravação para findAndModify () para substituir a preocupação de gravação padrão, enquanto você pode especificar uma preocupação de gravação para o método update () desde o MongoDB 2.6.

Ao modificar um único documento, o método findAndModify () e update () atualiza o documento automaticamente.

Tamlyn
fonte
1
Você sempre pode especificar uma preocupação de gravação para atualizar a operação. Além disso, desde o 3.2 (3.1.1 tecnicamente), você pode especificar a preocupação de gravação para o findAndModify também. jira.mongodb.org/browse/SERVER-6558
Asya Kamsky
Descobri que no MongDB 3.6, embora os estados do documento findAndModify()por padrão modifiquem apenas um documento e update()possam atualizar um ou mais documentos, quando eu uso um arrayFilters, findAndModify()atualiza todas as correspondências. Talvez seja um bug ??
WesternGun 16/02
Não há erros - os arrayFilters permitem atualizar vários elementos da matriz, mas eles ainda estão em um único documento.
Asya Kamsky
10

Uma classe útil de casos de uso é contadores e casos semelhantes. Por exemplo, dê uma olhada neste código (um dos testes do MongoDB): find_and_modify4.js .

Assim, findAndModifyvocê incrementa o contador e obtém seu valor incrementado em uma etapa. Compare: se você (A) executar esta operação em duas etapas e outra pessoa (B) fizer a mesma operação entre suas etapas, A e B poderão obter o mesmo último valor do contador em vez de dois diferentes (apenas um exemplo de possíveis problemas).

Roman Kuzmin
fonte
0

Usamos findAndModify () para operações de contador (inc ou dec) e outros campos únicos alteram casos. Ao migrar nosso aplicativo do Couchbase para o MongoDB, encontrei esta API para substituir o código GetAndlock (), modificar o conteúdo localmente, substituir () para salvar e Get () novamente para recuperar o documento atualizado. Com o mongoDB, eu apenas usei essa API única que retorna o documento atualizado.

Manju Kori
fonte