Gravar dados no Atlas MongoDB - Funções
Nesta página
- Modelo de dados
- Configuração do trecho
- Insert
- Inserir um único documento (
insertOne()
) - Inserir um ou mais documentos (
insertMany()
) - Update
- Atualizar um único documento (
updateOne()
) - Atualizar um ou mais documentos (
updateMany()
) - Documentos do Upsert
- Operadores de atualização de campo
- Operadores de atualização de array
- Excluir
- Excluir um único documento (
deleteOne()
) - Excluir um ou mais documentos (
deleteMany()
) - Gravações em massa
- Transações
Os exemplos nesta página demonstram como utilizar a API de query do MongoDB em uma função para inserir, atualizar e excluir dados em seu Atlas cluster.
Observação
As fontes de dados federadas não suportam operações de gravação.
Modelo de dados
Os exemplos nesta página usam uma coleção chamada store.items
que modela vários itens disponíveis para compra em uma loja virtual. Cada item possui um name
, um inventário quantity
e uma array de clientes reviews
.
{ "title": "Item", "required": ["_id", "name", "quantity", "reviews"], "properties": { "_id": { "bsonType": "objectId" }, "name": { "bsonType": "string" }, "quantity": { "bsonType": "int" }, "reviews": { "bsonType": "array", "items": { "bsonType": "object", "required": ["username", "comment"], "properties": { "username": { "bsonType": "string" }, "comment": { "bsonType": "string" } } } } } }
Configuração do trecho
Para usar um trecho de código em uma função, você deve primeiro instanciar um identificador de coleção do MongoDB:
exports = function() { const mongodb = context.services.get("mongodb-atlas"); const itemsCollection = mongodb.db("store").collection("items"); const purchasesCollection = mongodb.db("store").collection("purchases"); // ... paste snippet here ... }
Insert
Insira operações em um ou mais documentos e adicione-os a uma coleção MongoDB.
Retornam documentos que descrevem os resultados da operação.
Inserir um único documento (insertOne()
)
Você pode inserir um único documento usando o método collection.insertOne()
.
O seguinte trecho de função insere um único documento de item na coleção items
:
const newItem = { "name": "Plastic Bricks", "quantity": 10, "category": "toys", "reviews": [{ "username": "legolover", "comment": "These are awesome!" }] }; itemsCollection.insertOne(newItem) .then(result => console.log(`Successfully inserted item with _id: ${result.insertedId}`)) .catch(err => console.error(`Failed to insert item: ${err}`))
Inserir um ou mais documentos (insertMany()
)
Você pode inserir vários documentos ao mesmo tempo usando o método collection.insertMany()
.
O trecho de função abaixo insere vários documentos de itens na collection items
:
const doc1 = { "name": "basketball", "category": "sports", "quantity": 20, "reviews": [] }; const doc2 = { "name": "football", "category": "sports", "quantity": 30, "reviews": [] }; return itemsCollection.insertMany([doc1, doc2]) .then(result => { console.log(`Successfully inserted ${result.insertedIds.length} items!`); return result }) .catch(err => console.error(`Failed to insert documents: ${err}`))
Update
As operações de atualização localizam documentos existentes em uma collection do MongoDB e modificam seus dados. Você usa a sintaxe de query padrão do MongoDB para especificar quais documentos atualizar e operadores de atualização para descrever as alterações a serem aplicadas aos documentos correspondentes.
Ao executar operações de atualização, as Funções do Atlas adicionam temporariamente um campo reservado, _id__baas_transaction
, aos documentos. Depois que um documento é atualizado com êxito, as funções do Atlas removem esse campo.
Se você quiser usar outra ferramenta para modificar dados em uma coleção, certifique-se de $unset este campo antes de fazer alterações.
Por exemplo, se você estiver usando o shell mongosh para atualizar documentos na coleção de produtos, seu comando poderá se assemelhar ao código a seguir:
db.products.update( { sku: "unknown" }, { $unset: { _id__baas_transaction: "" } } )
Atualizar um único documento (updateOne()
)
Você pode atualizar um único documento usando o método collection.updateOne()
.
O seguinte snippet de função atualiza o name
de um único documento na coleção items
de lego
para blocks
e adiciona um price
de 20.99
:
const query = { "name": "lego" }; const update = { "$set": { "name": "blocks", "price": 20.99, "category": "toys" } }; const options = { "upsert": false }; itemsCollection.updateOne(query, update, options) .then(result => { const { matchedCount, modifiedCount } = result; if(matchedCount && modifiedCount) { console.log(`Successfully updated the item.`) } }) .catch(err => console.error(`Failed to update the item: ${err}`))
Como alternativa, você pode atualizar um único documento usando collection.findOneAndUpdate()
ou collection.findOneAndReplace()
. Ambos os métodos permitem encontrar, modificar e retornar o documento atualizado em uma única operação.
Atualizar um ou mais documentos (updateMany()
)
Você pode atualizar vários documentos em uma coleção usando o método collection.updateMany()
.
O seguinte trecho de função atualiza todos os documentos na coleção items
multiplicando seus valores de quantity
por 10
:
const query = {}; const update = { "$mul": { "quantity": 10 } }; const options = { "upsert": false } return itemsCollection.updateMany(query, update, options) .then(result => { const { matchedCount, modifiedCount } = result; console.log(`Successfully matched ${matchedCount} and modified ${modifiedCount} items.`) return result }) .catch(err => console.error(`Failed to update items: ${err}`))
Documentos do Upsert
Se uma operação de atualização não corresponder a nenhum documento na coleção, você poderá inserir automaticamente um único novo documento na coleção que corresponda à query de atualização definindo a opção upsert
como true
.
O trecho de função a seguir atualiza um documento na coleção items
que tem name
de board game
incrementando seu quantity
por 5
. A opção upsert
está habilitada, portanto, se nenhum documento tiver um valor name
de "board game"
, o MongoDB inserirá um novo documento com o campo name
definido como "board
game"
e o valor quantity
definido como 5
:
const query = { "name": "board games" }; const update = { "$inc": { "quantity": 5 } }; const options = { "upsert": true }; itemsCollection.updateOne(query, update, options) .then(result => { const { matchedCount, modifiedCount, upsertedId } = result; if(upsertedId) { console.log(`Document not found. Inserted a new document with _id: ${upsertedId}`) } else { console.log(`Successfully increased ${query.name} quantity by ${update.$inc.quantity}`) } }) .catch(err => console.error(`Failed to upsert document: ${err}`))
Operadores de atualização de campo
Os operadores de campo permitem modificar os campos e valores de um documento.
Definir o valor de um campo
Você pode utilizar o operador $set para definir o valor de um único campo sem afetar outros campos em um documento.
{ "$set": { "<Field Name>": <Value>, ... } }
Renomear um campo
Você pode usar o operador $rename para alterar o nome de um campo único em um documento.
{ "$rename": { "<Current Field Name>": <New Field Name>, ... } }
Incrementar um valor
Você pode utilizar o operador $inc para adicionar um número especificado ao valor atual de um campo. O número pode ser positivo ou negativo.
{ "$inc": { "<Field Name>": <Increment Number>, ... } }
Multiplicar um valor
Você pode usar o operador $mul para multiplicar um número especificado com o valor atual de um campo. O número pode ser positivo ou negativo.
{ "$mul": { "<Field Name>": <Multiple Number>, ... } }
Operadores de atualização de array
Operadores de arrays permitem trabalhar com valores dentro de arrays.
Faz push de um elemento para uma array
Você pode usar o operador $push para adicionar um valor ao final de um campo de array.
{ "$push": { "<Array Field Name>": <New Array Element>, ... } }
Retire o último elemento de uma array
Você pode usar o operador $pop para remover o primeiro ou último elemento de um campo de array. Especifique -1
para remover o primeiro elemento e 1
para remover o último elemento.
{ "$pop": { "<Array Field Name>": <-1 | 1>, ... } }
Adicionar um elemento único a uma array
Você pode usar o operador $addToSet para adicionar um valor a um campo de array se esse valor ainda não estiver incluído na array. Se o valor já estiver presente, $addToSet
não faz nada.
{ "$addToSet": { "<Array Field Name>": <Potentially Unique Value>, ... } }
Remover elementos de uma array
Você pode usar o operador $pull para remover todas as instâncias de quaisquer valores que correspondam a uma condição especificada de um campo de vetor.
{ "$pull": { "<Array Field Name>": <Value | Expression>, ... } }
Atualizar todos os elementos em uma array
Você pode utilizar o operador $[] (Todas as Atualizações Posicionais) para atualizar todos os elementos em um campo de array:
Exemplo
Considere uma collection students
que descreve alunos individuais em uma turma. Cada um dos documentos inclui um campo grades
que contém uma array de números:
{ "_id" : 1, "grades" : [ 85, 82, 80 ] } { "_id" : 2, "grades" : [ 88, 90, 92 ] } { "_id" : 3, "grades" : [ 85, 100, 90 ] }
A seguinte operação de atualização adiciona 10 a todos os valores na array grades
de cada aluno:
await students.updateMany( {}, { $inc: { "grades.$[]": 10 } }, )
Após a atualização, o valor de cada nota aumenta em intervalos de 10:
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 102 ] } { "_id" : 3, "grades" : [ 95, 110, 100 ] }
Atualizar elementos específicos em uma array
Você pode usar o operador $[element] (Atualização posicional filtrada) para atualizar elementos específicos em um campo de array baseado em um filtro de array:
Exemplo
Considere uma coleção students
que descreve alunos individuais em uma turma. Cada documento inclui um campo grades
que contém uma array de números, alguns dos quais são maiores que 100:
{ "_id" : 1, "grades" : [ 15, 92, 90 ] } { "_id" : 2, "grades" : [ 18, 100, 102 ] } { "_id" : 3, "grades" : [ 15, 110, 100 ] }
A seguinte operação de atualização define todos os valores de nota maiores que 100 para exatamente 100:
await students.updateMany( { }, { $set: { "grades.$[grade]" : 100 } }, { arrayFilters: [{ "grade": { $gt: 100 } }] } )
Após a atualização, todos os valores de nota maiores que 100 serão definidos como exatamente 100, e todas as outras notas não serão afetadas:
{ "_id" : 1, "grades" : [ 15, 92, 90 ] } { "_id" : 2, "grades" : [ 18, 100, 100 ] } { "_id" : 3, "grades" : [ 15, 100, 100 ] }
Excluir
As operações de exclusão localizam documentos existentes em uma coleção do MongoDB e os removem. Você usa a sintaxe de query MongoDB padrão para especificar quais documentos excluir.
Excluir um único documento (deleteOne()
)
Você pode excluir um único documento de uma coleção usando o método collection.deleteOne()
.
O seguinte snippet de função exclui um documento da coleção items
que tem um valor name
de lego
:
const query = { "name": "lego" }; itemsCollection.deleteOne(query) .then(result => console.log(`Deleted ${result.deletedCount} item.`)) .catch(err => console.error(`Delete failed with error: ${err}`))
Alternativamente, você pode atualizar um único documento usando collection.findOneAndDelete()
. Este método permite localizar, remover e devolver o documento excluído em uma única operação.
Excluir um ou mais documentos (deleteMany()
)
Você pode excluir vários itens de uma coleção utilizando o método collection.deleteMany()
.
O seguinte trecho exclui todos os documentos na coleção items
que não têm nenhum reviews
:
const query = { "reviews": { "$size": 0 } }; itemsCollection.deleteMany(query) .then(result => console.log(`Deleted ${result.deletedCount} item(s).`)) .catch(err => console.error(`Delete failed with error: ${err}`))
Gravações em massa
Uma escrita em massa combina múltiplas operações de escrita em uma única operação. Você pode emitir um comando de escrita em massa utilizando o método collection.bulkWrite()
.
exports = async function(arg){ const doc1 = { "name": "velvet elvis", "quantity": 20, "reviews": [] }; const doc2 = { "name": "mock turtleneck", "quantity": 30, "reviews": [] }; var collection = context.services.get("mongodb-atlas") .db("store") .collection("purchases"); return await collection.bulkWrite( [{ insertOne: doc1}, { insertOne: doc2}], {ordered:true}); };
Transações
O MongoDB oferece suporte a transações de vários documentos que permitem ler e gravar vários documentos atomicamente, mesmo em coleções.
Para realizar uma transação:
Obter e iniciar uma sessão de cliente com
client.startSession()
.Chame
session.withTransaction()
para definir a transação. O método usa uma função de chamada de resposta assíncrona e, opcionalmente, um objeto de configuração que define configurações personalizadas de leitura e gravação para a transação.session.withTransaction(async () => { // ... Run MongoDB operations in this callback }, { readPreference: "primary", readConcern: { level: "local" }, writeConcern: { w: "majority" }, }) Na função de chamada de resposta da transação, execute as queries do MongoDB que você deseja incluir na transação. Certifique-se de passar
session
para cada query para que ela seja incluída na transação.await accounts.updateOne( { name: userSubtractPoints }, { $inc: { browniePoints: -1 * pointVolume } }, { session } ); Se a chamada de resposta encontrar um erro, chame
session.abortTransaction()
para interromper a transação. Uma transação abortada não modifica nenhum dado.try { // ... } catch (err) { await session.abortTransaction(); } Quando a transação estiver concluída, ligue para
session.endSession()
para encerrar a sessão e recursos gratuitos.try { // ... } finally { await session.endSession(); }
O exemplo a seguir cria dois usuários, "henry" e "michelle", e a usa uma transação para mover "browniePoints" entre esses usuários Atomicamente:
exports = function () { const client = context.services.get("mongodb-atlas"); db = client.db("exampleDatabase"); accounts = db.collection("accounts"); browniePointsTrades = db.collection("browniePointsTrades"); // create user accounts with initial balances accounts.insertOne({ name: "henry", browniePoints: 42 }); accounts.insertOne({ name: "michelle", browniePoints: 144 }); // trade points between user accounts in a transaction tradeBrowniePoints( client, accounts, browniePointsTrades, "michelle", "henry", 5 ); return "Successfully traded brownie points."; }; async function tradeBrowniePoints( client, accounts, browniePointsTrades, userAddPoints, userSubtractPoints, pointVolume ) { // Step 1: Start a Client Session const session = client.startSession(); // Step 2: Optional. Define options to use for the transaction const transactionOptions = { readPreference: "primary", readConcern: { level: "local" }, writeConcern: { w: "majority" }, }; // Step 3: Use withTransaction to start a transaction, execute the callback, and commit (or abort on error) // Note: The callback for withTransaction MUST be async and/or return a Promise. try { await session.withTransaction(async () => { // Step 4: Execute the queries you would like to include in one atomic transaction // Important:: You must pass the session to the operations await accounts.updateOne( { name: userSubtractPoints }, { $inc: { browniePoints: -1 * pointVolume } }, { session } ); await accounts.updateOne( { name: userAddPoints }, { $inc: { browniePoints: pointVolume } }, { session } ); await browniePointsTrades.insertOne( { userAddPoints: userAddPoints, userSubtractPoints: userSubtractPoints, pointVolume: pointVolume, }, { session } ); }, transactionOptions); } catch (err) { // Step 5: Handle errors with a transaction abort await session.abortTransaction(); } finally { // Step 6: End the session when you complete the transaction await session.endSession(); } }