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?

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.


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.


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.


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).


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.