Atualizar Matrizes em um Documento
Nesta página
Visão geral
Neste guia, você pode aprender a usar os seguintes operadores de atualização de array para modificar uma array incorporada em um documento:
Operador posicional filtrado:
$[<identifier>]
Para obter uma lista de operadores de atualização de array, consulte Operadores de atualização na documentação do Manual do Servidor.
Especificando Elementos de Array
Os operadores posicionais especificam quais elementos da array devem ser atualizados. Você pode usar esses operadores para aplicar atualizações ao primeiro elemento, a todos os elementos ou a determinados elementos de uma array que correspondam a um critério.
Para especificar elementos em uma array com operadores posicionais, use a notação de ponto. A notação de ponto é uma sintaxe de acesso à propriedade para navegar em objetos BSON. Para saber mais, consulte notação de ponto.
O Primeiro Elemento de Array Correspondente
Para atualizar o primeiro elemento de array de cada documento que corresponda à sua query, use o operador posicional $
.
O operador posicional $
faz referência à array correspondente à consulta. Você não pode usar esse operador para fazer referência a uma array aninhada. Se quiser acessar uma array aninhada, use o operador posicional filtrado.
Importante
Não utilize o operador $
numa chamada upsert
porque o condutor trata $
como um nome de campo no documento de inserção.
Exemplo
Este exemplo usa o seguinte documento de amostra para mostrar como atualizar o primeiro elemento de array correspondente:
{ _id: ..., entries: [ { x: false, y: 1 }, { x: "hello", y: 100 }, { x: "goodbye", y: 1000 } ] }
O código a seguir mostra como incrementar um valor no primeiro elemento de array que corresponde a uma consulta.
A query corresponde aos elementos da array entries
em que o valor de x
é do tipo string
. A atualização aumenta o valor y
em 33
no primeiro elemento correspondente.
// Query for all elements in entries array where the value of x is a string const query = { "entries.x": { $type : "string" } }; // On first matched element, increase value of y by 33 const updateDocument = { $inc: { "entries.$.y": 33 } }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument);
Depois de executar a operação de atualização, o documento será semelhante ao seguinte:
{ _id: ..., entries: [ { x: false, y: 1 }, { x: "hello", y: 133 }, { x: "goodbye", y: 1000 } ] }
O exemplo inclui o campo entries.x
na query para corresponder à array à qual o operador $
aplica uma atualização. Se você omitir o campo entries.x
da query ao usar o operador $
em uma atualização, o driver não consegue identificar a array correspondente e gera o seguinte erro:
MongoServerError: The positional operator did not find the match needed from the query.
Correspondendo todos os elementos da array
Para executar a atualização em todos os elementos de array de cada documento que corresponda à sua consulta, use o operador posicional $[]
all.
Exemplo
Este exemplo usa os seguintes documentos de exemplo, que descrevem registros de chamadas telefônicas, para mostrar como atualizar todos os elementos correspondentes da array:
{ _id: ..., date: "5/15/2023", calls: [ { time: "10:08 AM", caller: "Mom", duration: 67 }, { time: "04:11 PM", caller: "Dad", duration: 121 }, { time: "06:36 PM", caller: "Grandpa", duration: 13 } ] }, { _id: ..., date: "5/16/2023", calls: [ { time: "11:47 AM", caller: "Mom", duration: 4 }, ] }
O código a seguir mostra como remover o campo duration
de todas as entradas de array calls
no documento cuja date
é "5/15/2023"
:
// Query for all documents where date is the string "5/15/2023" const query = { date: "5/15/2023" }; // For each matched document, remove duration field from all entries in calls array const updateDocument = { $unset: { "calls.$[].duration": "" } }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument);
Após executar a operação de atualização, os documentos se assemelham ao seguinte:
{ _id: ..., date: "5/15/2023", calls: [ { time: "10:08 AM", caller: "Mom" }, { time: "04:11 PM", caller: "Dad" }, { time: "06:36 PM", caller: "Grandpa" } ] }, { _id: ..., date: "5/16/2023", calls: [ { time: "11:47 AM", caller: "Mom", duration: 4 }, ] }
Combinando vários elementos da matriz
Para realizar uma atualização em todos os elementos da array incorporados de cada documento que corresponda à sua query, use o operador posicional filtrado $[<identifier>]
.
O operador posicional filtrado $[<identifier>]
especifica os elementos de array correspondentes no documento de atualização. Para identificar quais elementos de array devem corresponder, emparelhe este operador com <identifier>
em um objeto arrayFilters
.
O espaço reservado <identifier>
representa um elemento do campo de array Você deve selecionar um valor para <identifier>
que comece com uma letra minúscula e contenha apenas caracteres alfanuméricos.
Uso
Você pode usar um operador posicional filtrado em uma operação de atualização. Uma operação de atualização utiliza uma query, um documento de atualização e, opcionalmente, um objeto de opções como parâmetros.
As seguintes etapas descrevem como utilizar um operador posicional filtrado em uma operação de atualização:
Formate seu documento de atualização da seguinte maneira:
{ $<operator>: { "<array>.$[<identifier>].<arrayField>": <updateParameter> } } Este documento de atualização contém os seguintes espaços reservados:
$<operator>
: O operador de atualização de array<array>
: A array no documento a ser atualizada<identifier>
: O identificador do operador posicional filtrado<arrayField>
: O campo no elemento da array<array>
a ser atualizado<updateParameter>
: O valor que descreve a atualização
Adicione os critérios correspondentes no objeto
arrayFilters
. Esse objeto é uma array de consultas que especifica quais elementos de array devem ser incluídos na atualização. Defina este objeto em um parâmetrooptions
:arrayFilters: [ { "<identifier>.<arrayField1>": <updateParameter1> }, { "<identifier>.<arrayField2>": <updateParameter2> }, ... ] Passe a query, o documento de atualização e as opções para um método de atualização. O seguinte código de amostra mostra como chamar o método
updateOne()
com estes parâmetros:await myColl.updateOne(query, updateDocument, options);
Exemplo
Este exemplo usa os seguintes documentos de exemplo, que descrevem listas de compras para receitas específicas, para mostrar como atualizar determinados elementos de array correspondentes:
{ _id: ..., date: "11/12/2023", items: [ { item: "Scallions", quantity: 3, recipe: "Fried rice" }, { item: "Mangos", quantity: 4, recipe: "Salsa" }, { item: "Pork shoulder", quantity: 1, recipe: "Fried rice" }, { item: "Sesame oil", quantity: 1, recipe: "Fried rice" } ] }, { _id: ..., date: "11/20/2023", items: [ { item: "Coffee beans", quantity: 1, recipe: "Coffee" } ] }
Suponha que você queira aumentar a quantidade de itens que você compra para uma receita em sua ida ao supermercado "11/12/2023"
. Você deseja dobrar a quantidade se o item atender a todos os critérios a seguir:
O item é para a receita de
"Fried rice"
.O nome do item não inclui a palavra
"oil"
.
Para duplicar o valor de quantity
nas entradas de array correspondentes, use o operador posicional filtrado como mostrado no seguinte código:
// Query for all documents where date is the string "11/12/2023" const query = { date: "11/12/2023" }; // For each matched document, change the quantity of items to 2 const updateDocument = { $mul: { "items.$[i].quantity": 2 } }; // Update only non-oil items used for fried rice const options = { arrayFilters: [ { "i.recipe": "Fried rice", "i.item": { $not: { $regex: "oil" } }, } ] }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument, options);
A atualização multiplicou o valor quantity
por 2
para itens que corresponderam aos critérios. O item "Sesame oil"
não corresponde aos critérios no objeto arrayFilters
e, portanto, foi excluído da atualização. Os seguintes documentos refletem estas alterações:
{ _id: ..., date: "11/12/2023", items: [ { item: "Scallions", quantity: 6, recipe: "Fried rice" }, { item: "Mangos", quantity: 4, recipe: "Salsa" }, { item: "Pork shoulder", quantity: 2, recipe: "Fried rice" }, { item: "Sesame oil", quantity: 1, recipe: "Fried rice" } ] }, { _id: ..., date: "11/20/2023", items: [ { item: "Coffee beans", quantity: 1, recipe: "Coffee" } ] }