Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ / /

db.collection.findAndModify()

Nesta página

  • Definição
  • Compatibilidade
  • Sintaxe
  • Retornar dados
  • Comportamento
  • Exemplos

MongoDB com drivers

Esta página documenta um método mongosh. Para ver o método equivalente em um driver MongoDB, consulte a página correspondente da sua linguagem de programação:

C#Java SyncNode.jsPyMongoCC++GoJava RSKotlin CoroutineKotlin SyncPHPMongoidRustScala
db.collection.findAndModify(document)

Importante

Método de mongosh obsoleto

Use findOneAndUpdate(), findOneAndDelete() ou findOneAndReplace() em vez disso.

Atualiza e retorna um único documento. Por padrão, o documento devolvido não inclui as modificações feitas na atualização. Para retornar o documento com as modificações feitas na atualização, use a opção new .

Você pode utilizar o db.collection.findAndModify() para implantações hospedadas nos seguintes ambientes:

  • MongoDB Atlas: o serviço totalmente gerenciado para implantações do MongoDB na nuvem

  • MongoDB Enterprise: a versão autogerenciada e baseada em assinatura do MongoDB

  • MongoDB Community: uma versão com código disponível, de uso gratuito e autogerenciada do MongoDB

Alterado na versão 5.0.

O método findAndModify() tem o seguinte formato:

db.collection.findAndModify({
query: <document>,
sort: <document>,
remove: <boolean>,
update: <document or aggregation pipeline>,
new: <boolean>,
fields: <document>,
upsert: <boolean>,
bypassDocumentValidation: <boolean>,
writeConcern: <document>,
maxTimeMS: <integer>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
let: <document> // Added in MongoDB 5.0
});

O método db.collection.findAndModify() usa um parâmetro de documento com os seguintes campos de documentos incorporados:

Parâmetro
Tipo
Descrição

query

documento

Opcional. Os critérios de seleção para a modificação. O query campo emprega os mesmos seletores de query usados no db.collection.find() método. Embora a query possa corresponder a vários documentos, db.collection.findAndModify() selecionará somente um documento para modificar.

Se não for especificado, o padrão será um documento vazio.

Se o argumento de consulta não for um documento, a operação será executada.

sort

documento

Opcional. Determina qual documento a operação atualiza se a query selecionar vários documentos. atualiza o primeiro documento na ordem de classificação especificada por estedb.collection.findAndModify() argumento.

Se o argumento de classificação não for um documento, ocorrerá um erro com a operação.

O MongoDB não armazena documentos em uma collection em uma ordem específica. Ao ordenar em um campo que contém valores duplicados, os documentos que contêm esses valores podem ser retornados em qualquer ordem.

Se desejar uma ordem de classificação consistente, inclua pelo menos um campo em sua ordenação que contenha valores exclusivos. A maneira mais fácil de garantir isso é incluir o campo _id em sua query de ordenação.

Consulte Consistência de classificação para obter mais informações.

remove

booleano

Deve especificar o campo remove ou update. Remove o documento especificado no campo query. Define como true para remover o documento selecionado. O padrão é false.

update

documento ou array

Deve especificar o campo remove ou update. Executa uma atualização do documento selecionado.

new

booleano

Opcional. Quando true, retorna o documento atualizado em vez do original. O padrão é false.

fields

documento

Opcional. Um subconjunto de campos para retornar. O documento fields especifica a inclusão de um campo com 1, como em: fields: { <field1>: 1, <field2>: 1, ... }.

Se o argumento fields não for um documento, a operação vai gerar erros.

Para mais informações sobre projeção, consulte fields Projeção.

upsert

booleano

Opcional. Usado em conjunto com o campo update.

Quando,true findAndModify() ou:

  • Cria um novo documento se nenhum documento corresponder a query. Para obter mais detalhes, consulte comportamento upsert.

  • Atualiza um único documento que corresponda a query.

Para evitar várias atualizações, certifique-se de que os query campo sejam indexados de forma exclusiva.Consulte Upsert com índice exclusivo para obter um exemplo.

O padrão é false, que não insere um novo documento quando nenhuma correspondência é encontrada.

bypassDocumentValidation

booleano

Opcional. Habilita o db.collection.findAndModify() para ignorar a validação do documento durante a operação. Isso permite atualizar documentos que não atendem aos requisitos de validação.

writeConcern

documento

Opcional. Um documento que expressa o write concern. Omitir para usar o write concern padrão.

Não defina explicitamente a preocupação de gravação para a operação se for executada em uma transação. Para usar write concern com transações, consulte Transações e write concern.

maxTimeMS

non-negative integer

Opcional.

Especifica um limite de tempo em milissegundos. Se você não especificar um valor para maxTimeMS, as operações não atingirão o tempo limite. Um valor 0 especifica explicitamente o comportamento ilimitado padrão.

O MongoDB encerra as operações que excedem o limite de tempo alocado usando o mesmo mecanismo de db.killOp(). O MongoDB só encerra uma operação em um de seus pontos de interrupção designados.

collation

documento

Opcional.

Especifica o agrupamento a ser usado para a operação.

A colocação permite que os usuários especifiquem regras específicas do idioma para comparação de strings, como regras para letras maiúsculas e marcas de acento.

A opção de agrupamento tem a seguinte sintaxe:

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

Ao especificar agrupamento, o campo locale é obrigatório; todos os outros campos de agrupamento são opcionais. Para obter descrições dos campos, consulte Documento de agrupamento.

Se o agrupamento não for especificado, mas a coleção tiver um agrupamento padrão (consulte db.createCollection()), a operação usará o agrupamento especificado para a coleção.

Se nenhum agrupamento for especificado para a coleção ou para as operações, o MongoDB usa a comparação binária simples usada nas versões anteriores para comparações de strings.

Você não pode especificar vários agrupamentos para uma operação. Por exemplo, você não pode especificar agrupamentos diferentes por campo ou, se estiver realizando uma busca com uma classificação, não poderá usar um agrupamento para a busca e outro para a classificação.

arrayFilters

array

Opcional. Uma array de documentos de filtro que determina quais elementos da array modificar para uma operação de atualização em um campo da array.

No documento de atualização, use o operador posicional filtrado $[<identifier>] para definir um identificador, que você então faz referência nos documentos de filtro de array. Você não pode ter um documento de filtro de array para um identificador se o identificador não estiver incluído no documento de atualização.

O <identifier> deve começar com uma letra minúscula e conter apenas caracteres alfanuméricos.

Você pode incluir o mesmo identificador várias vezes no documento de atualização; entretanto, para cada identificador distinto ($[identifier]) no documento de atualização, você deve especificar exatamente um documento de filtro de array correspondente. Ou seja, não é possível especificar vários documentos de filtro de array para o mesmo identificador. Por exemplo, se a instrução de atualização incluir o identificador x (possivelmente várias vezes), você não poderá especificar o seguinte para arrayFilters que inclui 2 documentos de filtro separados para x:

// INVALID
[
{ "x.a": { $gt: 85 } },
{ "x.b": { $gt: 80 } }
]

No entanto, você pode especificar condições compostas no mesmo identificador em um único documento de filtro, como nos exemplos a seguir:

// Example 1
[
{ $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 2
[
{ $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 3
[
{ "x.a": { $gt: 85 }, "x.b": { $gt: 80 } }
]

Para obter exemplos, consulte Especificar arrayFilters para uma operação de atualização de matriz.

arrayFilters não está disponível para atualizações que usam um pipeline de agregação

documento

Opcional.

Especifica um documento com uma lista de variáveis. Isso permite que você melhore a legibilidade do comando separando as variáveis do texto da query.

A sintaxe do documento é:

{
<variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n>
}

A variável é definida para o valor retornado pela expressão e não pode ser alterada posteriormente.

Para acessar o valor de uma variável no comando, use o prefixo de dois cifrões ($$) junto com o nome da variável no formato $$<variable_name>. Por exemplo: $$targetTotal.

Para usar uma variável para filtrar os resultados, você deve acessar a variável dentro do operador $expr.

Para um exemplo completo utilizando let e variáveis, consulte Utilizar Variáveis let no .

Novidades na versão 5.0.

Para remover operações, se a query corresponder a um documento, findAndModify() retorna o documento removido. Se a query não corresponder a um documento para remover, findAndModify() retornará null.

Para operações de atualização, o findAndModify() retorna um dos seguintes:

  • Se o parâmetro new não estiver configurado ou for false:

    • o documento de pré-modificação se a query corresponder a um documento;

    • caso contrário, null.

  • Se new for true:

    • o documento atualizado se a query retornar uma correspondência;

    • o documento inserido se upsert: true e nenhum documento corresponder à query;

    • caso contrário, null.

Importante

Consistência de linguagem

Como parte de tornar a projeção find() e findAndModify() consistente com o estágio $project da agregação,

A opção fields usa um documento no seguinte formato:

{ field1: <value>, field2: <value> ... }
Projeção
Descrição

<field>: <1 or true>

Especifica a inclusão de um campo. Se você especificar um número inteiro diferente de zero para o valor de projeção, a operação tratará o valor como true.

<field>: <0 or false>

Especifica a exclusão de um campo.

"<field>.$": <1 or true>

Usa o operador de projeção de array $ para retornar o primeiro elemento que corresponde à condição de consulta no campo de array. Se você especificar um número inteiro diferente de zero para o valor de projeção, a operação tratará o valor como true.

Não disponível para visualizações.

<field>: <array projection>

Usa os operadores de projeção de array ($elemMatch, $slice) para especificar os elementos da array a serem incluídos.

Não disponível para visualizações.

<field>: <aggregation expression>

Especifica o valor do campo projetado.

Com o uso de expressões de agregação e sintaxe, incluindo o uso de literais e variáveis de agregação, você pode projetar novos campos ou projetar campos existentes com novos valores.

  • Se você especificar um literal não numérico e não booleano (como uma string literal ou uma array ou uma expressão de operador) para o valor de projeção, o campo será projetado com o novo valor, por exemplo:

    • { field: [ 1, 2, 3, "$someExistingField" ] }

    • { field: "New String Value" }

    • { field: { status: "Active", total: { $sum: "$existingArray" } } }

  • Para projetar um valor literal para um campo, use a expressão de aggregation $literal, por exemplo:

    • { field: { $literal: 5 } }

    • { field: { $literal: true } }

    • { field: { $literal: { fieldWithValue0: 0, fieldWithValue1: 1 } } }

Para campos em documentos incorporados, você pode especificar o campo usando:

  • notação de pontos, por exemplo "field.nestedfield": <value>

  • formato aninhado, por exemplo { field: { nestedfield: <value> } }

O campo _id é incluído nos documentos retornados por padrão, a menos que você especifique explicitamente _id: 0 na projeção para suprimir o campo.

Uma projection não pode conter especificações de inclusão e exclusão, com exceção do campo _id:

  • Em projeções que incluem explicitamente campos, o campo _id é o único campo que você pode excluir explicitamente.

  • Em projeções que excluem explicitamente campos, o campo _id é o único campo que você pode incluir explicitamente; entretanto, o campo _id é incluído por padrão.

Para obter mais informações sobre "projection", consulte também:

Os upserts podem criar documentos duplicados, a menos que haja um índice único para evitar duplicatas.

Considere um exemplo em que nenhum documento com o nome Andy existe e vários clientes emitem o seguinte comando ao mesmo tempo:

db.people.findAndModify(
{
query: { name: "Andy" },
update: { $inc: { score: 1 } },
upsert: true
}
)

Se todas as operações findOneAndUpdate() terminarem a fase de query antes que qualquer cliente insira dados com êxito e não houver um índice exclusivo no campo name , cada operação findOneAndUpdate() poderá resultar em uma inserção, criando vários documentos com name: Andy.

Um índice único no campo name garante que apenas um documento seja criado. Com um índice único em vigor, as múltiplas operações findOneAndUpdate() agora exibem o seguinte comportamento:

  • Exatamente uma operação findOneAndUpdate() inserirá com sucesso um novo documento.

  • Outras operações findOneAndUpdate() atualizam o documento recém-inserido ou falham devido a uma colisão de chave exclusiva.

    Para que outras operações do findOneAndUpdate() atualizem o documento recém-inserido, todas as seguintes condições devem ser atendidas:

    • A collection de destino tem um índice único que causaria um erro de chave duplicado.

    • A operação de atualização não é updateMany ou multi é false.

    • A condição de correspondência de atualização é:

      • Um único predicado de igualdade. Por exemplo { "fieldA" : "valueA" }

      • Um E lógico de predicados de igualdade. Por exemplo { "fieldA" : "valueA", "fieldB" : "valueB" }

    • O campo no predicado de igualdade correspondem ao campo no padrão de chave de índice único.

    • A operação de atualização não modifica nenhum campo no padrão de chave de índice único.

A tabela a seguir mostra exemplos de operações upsert que, quando ocorre uma colisão de chaves, resultam em uma atualização ou falha.

Padrão de chave de índice exclusivo
Operação de atualização
Resultado
{ name : 1 }
db.people.updateOne(
{ name: "Andy" },
{ $inc: { score: 1 } },
{ upsert: true }
)

O campo score do documento correspondente é incrementado em 1.

{ name : 1 }
db.people.updateOne(
{ name: { $ne: "Joe" } },
{ $set: { name: "Andy" } },
{ upsert: true }
)

A operação falha porque modifica o campo no padrão de chave de índice único (name).

{ name : 1 }
db.people.updateOne(
{ name: "Andy", email: "andy@xyz.com" },
{ $set: { active: false } },
{ upsert: true }
)

A operação falha porque os campos de predicados de igualdade (name, email) não correspondem ao campo chave de índice (name).

Para usar findAndModify em uma collection fragmentada:

  • Se você só tiver como alvo um shard, pode usar uma chave de shard parcial no campo query ou,

  • Você pode fornecer uma condição de igualdade em uma chave de shard completa no campo query.

Os documentos em uma coleção fragmentada podem não ter campos de chave de fragmento. Para direcionar um documento que não tem a chave de fragmento, você pode usar a correspondência de igualdade nullem conjunto com outra condição de filtro (como no campo _id). Por exemplo:

{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key

Você pode atualizar o valor da chave de fragmento de um documento, a menos que o campo de chave de fragmento seja o campo de _id imutável.

Aviso

Os documentos em coleções fragmentadas podem não ter os campos chave de fragmentado. Tome cuidado para evitar remover acidentalmente a chave de fragmento ao alterar o valor dela em um documento.

Para atualizar o valor da chave de fragmento existente com db.collection.findAndModify():

  • Você deve executar em um mongos. Não emita a operação diretamente no fragmento.

  • Você deve executar em uma transação ou como uma gravação repetível.

  • Você deve incluir um filtro de igualdade na chave de shard completa.

Os documentos em coleções fragmentadas podem não ter os campos de chave de fragmento. Para usar db.collection.findAndModify() para configurar a chave de fragmento ausente do documento:

  • Você deve executar em um mongos. Não emita a operação diretamente no fragmento.

  • Você deve executar em uma transação ou como retryable write se o novo valor da chave de shard não for null.

  • Você deve incluir um filtro de igualdade na chave de shard completa.

Dica

Como um valor de chave ausente é retornado como parte de uma correspondência de igualdade nula, para evitar a atualização de uma chave de valor nulo, inclua condições de consulta (como no campo _id) conforme apropriado.

Veja também:

O método db.collection.findAndModify() adiciona compatibilidade para a opção bypassDocumentValidation, que permite ignorar a validação de documentos ao inserir ou atualizar documentos em uma coleção com regras de validação.

Ao atualizar um documento, db.collection.findAndModify() e o método updateOne() operam de forma diferente:

  • Se vários documentos corresponderem aos critérios de atualização para db.collection.findAndModify(), você poderá especificar uma sort para fornecer alguma medida de controle sobre qual documento atualizar.

    updateOne() atualiza o primeiro documento que corresponde.

  • Por padrão, db.collection.findAndModify() retorna a versão pré-modificada do documento. Para obter o documento atualizado, use a opção new.

    O método updateOne() 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 lógica adicional para identificar o documento atualizado.

Se modificar um único documento, ambos o db.collection.findAndModify() e o método updateOne() atualizam atomicamente o documento. Consulte Atomicidade e transações para obter mais detalhes sobre as interações e a ordem das operações desses métodos.

db.collection.findAndModify() pode ser usado dentro de transações distribuídas.

Importante

Na maioria dos casos, uma transação distribuída incorre em um custo de desempenho maior do que as gravações de um único documento, e a disponibilidade de transações distribuídas não deve substituir o design eficaz do esquema. Em muitos cenários, o modelo de dados desnormalizado (documentos e arrays incorporados) continuará a ser ideal para seus dados e casos de uso. Ou seja, para muitos cenários, modelar seus dados adequadamente minimizará a necessidade de transações distribuídas.

Para considerações adicionais sobre o uso de transações (como limite de tempo de execução e limite de tamanho do oplog), consulte também Considerações de produção.

Você pode criar coleção e índices dentro de uma transação distribuída se a transação não for uma transação de gravação cross-fragmento.

db.collection.findAndModify() com upsert: true pode ser executado em uma coleção existente ou em uma coleção inexistente. Se for executada em uma coleção inexistente, a operação cria a coleção.

Não defina explicitamente a preocupação de gravação para a operação se for executada em uma transação. Para usar write concern com transações, consulte Transações e write concern.

Se uma operação db.collection.findAndModify() conseguir localizar e modificar um documento, ela adicionará uma entrada no oplog (log de operações). Se a operação falhar ou não encontrar um documento para modificar, ela não adicionará uma entrada no oplog.

O método a seguir atualiza e retorna um documento existente na collection de pessoas onde o documento corresponde aos critérios de query:

db.people.findAndModify({
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
})

Este método executa as seguintes ações:

  1. A query localiza um documento na collection people onde o campo name tem o valor Tom, o campo state tem o valor active e o campo rating tem um valor greater than 10.

  2. O sort classifica os resultados da query em ordem crescente. Se vários documentos atenderem à condição query, o método selecionará para modificação o primeiro documento conforme ordenado por este sort.

  3. A atualização increments do valor do campo score por 1.

  4. O método retorna o documento original (ou seja, pré-modificação) selecionado para esta atualização:

    {
    "_id" : ObjectId("50f1e2c99beb36a0f45c6453"),
    "name" : "Tom",
    "state" : "active",
    "rating" : 100,
    "score" : 5
    }

    Para retornar o documento atualizado, adicione a opção new:true ao método.

    Se nenhum documento corresponder à condição query, o método retornará null.

O método a seguir inclui a opção upsert: true para a operação update atualizar um documento correspondente ou, se não existir nenhum documento correspondente, criar um novo documento:

db.people.findAndModify({
query: { name: "Gus", state: "active", rating: 100 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true
})

Se encontrar um documento correspondente, o método executará uma atualização.

Se não encontrar um documento correspondente, o método criará um novo documento. Como o método incluiu a opção sort, ele retorna um documento vazio { } como o documento original (pré-modificação):

{ }

Se o método não incluiu uma opção sort , o método retorna null.

null

O método seguinte inclui a opção upsert: true e a opção new:true. O método atualiza um documento correspondente e retorna o documento atualizado ou, se não existir nenhum documento correspondente, insere um documento e retorna o documento recém-inserido no campo value.

No exemplo a seguir, nenhum documento na collection people corresponde à condição query:

db.people.findAndModify({
query: { name: "Pascal", state: "active", rating: 25 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true,
new: true
})

O método retorna o documento recém-inserido:

{
"_id" : ObjectId("50f49ad6444c11ac2448a5d6"),
"name" : "Pascal",
"rating" : 25,
"score" : 1,
"state" : "active"
}

Ao incluir uma especificação sort no campo rating, o exemplo seguinte remove da collection people um único documento com o valor state de active e o menor rating entre os documentos correspondentes:

db.people.findAndModify(
{
query: { state: "active" },
sort: { rating: 1 },
remove: true
}
)

O método retorna o documento excluído:

{
"_id" : ObjectId("52fba867ab5fdca1299674ad"),
"name" : "XYZ123",
"score" : 1,
"state" : "active",
"rating" : 3
}

A colocação permite que os usuários especifiquem regras específicas do idioma para comparação de strings, como regras para letras maiúsculas e marcas de acento.

Uma coleção myColl possui os seguintes documentos:

{ _id: 1, category: "café", status: "A" }
{ _id: 2, category: "cafe", status: "a" }
{ _id: 3, category: "cafE", status: "a" }

A seguinte operação inclui a opção coleção:

db.myColl.findAndModify({
query: { category: "cafe", status: "a" },
sort: { category: 1 },
update: { $set: { status: "Updated" } },
collation: { locale: "fr", strength: 1 }
});

A operação retorna o seguinte documento:

{ "_id" : 1, "category" : "café", "status" : "A" }

Observação

arrayFilters não está disponível para atualizações que usam um pipeline de agregação

Ao atualizar um campo de array, você pode especificar arrayFilters que determinam quais elementos de array atualizar.

Observação

arrayFilters não está disponível para atualizações que usam um pipeline de agregação

Crie uma collection students com os seguintes documentos:

db.students.insertMany( [
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
] )

Para atualizar todos os elementos que são maiores ou iguais a 100 no array grades, utilize o operador posicional filtrado $[<identifier>] com a opção arrayFilters no método db.collection.findAndModify():

db.students.findAndModify({
query: { grades: { $gte: 100 } },
update: { $set: { "grades.$[element]" : 100 } },
arrayFilters: [ { "element": { $gte: 100 } } ]
})

A operação atualiza o campo grades para um único documento e, após a operação, a collection tem os seguintes documentos:

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }

Observação

arrayFilters não está disponível para atualizações que usam um pipeline de agregação

Crie uma collection students2 com os seguintes documentos:

db.students2.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
] )

A operação a seguir localiza um documento em que o campo _id é igual a 1 e usa o operador posicional filtrado $[<identifier>] com arrayFilters para atualizar o mean para todos os elementos na array grades onde a nota é maior maior ou igual a 85.

db.students2.findAndModify({
query: { _id : 1 },
update: { $set: { "grades.$[elem].mean" : 100 } },
arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
})

A operação atualiza o campo grades para um único documento e, após a operação, a collection tem os seguintes documentos:

{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}

db.collection.findAndModify() pode aceitar um pipeline de agregação para a atualização. O pipeline pode consistir nas seguintes etapas:

O uso do aggregation pipeline permite uma instrução de atualização mais expressiva, como atualizações condicionais Express com base em valores de campo atuais ou atualização de um campo usando o valor de outro(s) campo(s).

Por exemplo, criar uma collection students2 com os seguintes documentos:

db.students2.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
] )

A operação a seguir localiza um documento em que o campo _id é igual a 1 e usa um aggregation pipeline para calcular um novo total de campo a partir do campo grades:

db.students2.findAndModify( {
query: { "_id" : 1 },
update: [ { $set: { "total" : { $sum: "$grades.grade" } } } ], // The $set stage is an alias for ``$addFields`` stage
new: true
} )

Observação

O $set usado no pipeline se refere ao estágio de aggregation $set e não ao operador de atualização $set.

A operação retorna o documento atualizado:

{
"_id" : 1,
"grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ],
"total" : 250
}

Novidades na versão 5.0.

Para definir variáveis que você pode acessar em outro lugar no comando, use a opção let .

Observação

Para filtrar resultados usando uma variável, você deve acessar a variável dentro do operador $expr.

Criar uma coleção cakeFlavors:

db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )

O exemplo a seguir define uma variável targetFlavor em let e usa a variável para alterar o sabor do bolo de cereja para laranja:

db.cakeFlavors.findAndModify( {
query: {
$expr: { $eq: [ "$flavor", "$$targetFlavor" ] }
},
update: { flavor: "orange" },
let: { targetFlavor: "cherry" }
} )

A partir do MongoDB 7.0, você pode usar a nova variável de sistemaUSER_ROLES para retornar funções de usuário .

O exemplo nesta seção mostra atualizações de campos em uma collection que contém informações médicas. O exemplo lê os roles atuais do usuário da variável de sistema USER_ROLES e só executa as atualizações se o usuário tiver um role específico.

Para usar uma variável do sistema, adicione $$ ao início do nome da variável. Especifique a variável de sistema USER_ROLES como $$USER_ROLES.

O exemplo cria estes usuários:

  • James com um role Billing.

  • Michelle com um role Provider.

Execute as seguintes etapas para criar os roles, os usuários e a collection:

1

Crie roles denominados Billing e Provider com os recursos e privilégios exigidos.

Executar:

db.createRole( { role: "Billing", privileges: [ { resource: { db: "test",
collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
db.createRole( { role: "Provider", privileges: [ { resource: { db: "test",
collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
2

Crie usuários chamados James e Michelle com os roles exigidos.

db.createUser( {
user: "James",
pwd: "js008",
roles: [
{ role: "Billing", db: "test" }
]
} )
db.createUser( {
user: "Michelle",
pwd: "me009",
roles: [
{ role: "Provider", db: "test" }
]
} )
3

Executar:

db.medical.insertMany( [
{
_id: 0,
patientName: "Jack Jones",
diagnosisCode: "CAS 17",
creditCard: "1234-5678-9012-3456"
},
{
_id: 1,
patientName: "Mary Smith",
diagnosisCode: "ACH 01",
creditCard: "6541-7534-9637-3456"
}
] )

Faça login como Michelle, que tem o role Provider, e execute uma atualização:

1

Executar:

db.auth( "Michelle", "me009" )
2

Executar:

// Attempt to find and modify document
db.medical.findAndModify( {
query:
{ $and: [
{
// Only update the document for Mary Smith
patientName: { $eq: "Mary Smith" }
},
{
// User must have the Provider role to perform the update
$expr: { $ne: [ {
$setIntersection: [ [ "Provider" ], "$$USER_ROLES.role" ]
}, [] ] }
}
]
},
// Update document
update: {
patientName: "Mary Smith",
diagnosisCode: "ACH 03",
creditCard: "6541-7534-9637-3456"
}
} )

O exemplo anterior usa $setIntersection para retornar documentos onde a interseção entre a string "Provider" e os roles de usuário do $$USER_ROLES.role não está vazia. Michelle tem o role Provider, então a atualização é executada.

Em seguida, faça login como James, que não tem o role Provider e tente realizar a mesma atualização:

1

Executar:

db.auth( "James", "js008" )
2

Executar:

// Attempt to find and modify document
db.medical.findAndModify( {
query:
{ $and: [
{
// Only update the document for Mary Smith
patientName: { $eq: "Mary Smith" }
},
{
// User must have the Provider role to perform the update
$expr: { $ne: [ {
$setIntersection: [ [ "Provider" ], "$$USER_ROLES.role" ]
}, [] ] }
}
]
},
// Update document
update: {
patientName: "Mary Smith",
diagnosisCode: "ACH 03",
creditCard: "6541-7534-9637-3456"
}
} )

O exemplo anterior não atualiza nenhum documento.

Voltar

db.collection.find