Write Data in MongoDB Atlas - Functions
On this page
- Data Model
- Snippet Setup
- Insert
- Insert a Single Document (
insertOne()
) - Insert One or More Documents (
insertMany()
) - Update
- Update a Single Document (
updateOne()
) - Update One or More Documents (
updateMany()
) - Upsert Documents
- Field Update Operators
- Array Update Operators
- Delete
- Delete a Single Document (
deleteOne()
) - Delete One or More Documents (
deleteMany()
) - Bulk Writes
- Transactions
The examples on this page demonstrate how to use the MongoDB Query API in a function to insert, update, and delete data in your Atlas cluster.
Note
Federated data sources do not support write operations.
Data Model
The examples on this page use a collection named store.items
that
models various items available for purchase in an online store. Each
item has a name
, an inventory quantity
, and an array of customer
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" } } } } } }
Snippet Setup
To use a code snippet in a function, you must first instantiate a MongoDB collection handle:
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
Insert operations take one or more documents and add them to a MongoDB collection.
They return documents that describe the results of the operation.
Insert a Single Document (insertOne()
)
You can insert a single document using the
collection.insertOne()
method.
The following Function snippet inserts a single item
document into the items
collection:
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}`))
Insert One or More Documents (insertMany()
)
You can insert multiple documents at the same time using the
collection.insertMany()
method.
The following Function snippet inserts multiple item
documents into the items
collection:
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
Update operations find existing documents in a MongoDB collection and modify their data. You use standard MongoDB query syntax to specify which documents to update and update operators to describe the changes to apply to matching documents.
While running update operations, Atlas Functions temporarily add a
reserved field, _id__baas_transaction
, to documents. Once a document is
successfully updated, Atlas Functions remove this field.
If you want to use another tool to modify data in a collection, ensure that you $unset this field prior to making changes.
For example, if you are using the mongosh shell to update documents in the products collection, your command might resemble the following code:
db.products.update( { sku: "unknown" }, { $unset: { _id__baas_transaction: "" } } )
Update a Single Document (updateOne()
)
You can update a single document using the
collection.updateOne()
method.
The following Function snippet updates the name
of a single document in the items
collection from lego
to
blocks
and adds a price
of 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}`))
Alternatively, you can update a single document using
collection.findOneAndUpdate()
or
collection.findOneAndReplace()
. Both methods allow you to
find, modify, and return the updated document in a single operation.
Update One or More Documents (updateMany()
)
You can update multiple documents in a collection using the
collection.updateMany()
method.
The following Function snippet updates all documents
in the items
collection by multiplying their quantity
values by
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}`))
Upsert Documents
If an update operation does not match any document in the collection,
you can automatically insert a single new document into the collection
that matches the update query by setting the upsert
option to
true
.
The following Function snippet updates a document in
the items
collection that has a name
of board game
by
incrementing its quantity
by 5
. The upsert
option is
enabled, so if no document has a name
value of "board game"
then
MongoDB inserts a new document with the name
field set to "board
game"
and the quantity
value set to 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}`))
Field Update Operators
Field operators let you modify the fields and values of a document.
Set the Value of a Field
You can use the $set operator to set the value of a single field without affecting other fields in a document.
{ "$set": { "<Field Name>": <Value>, ... } }
Rename a Field
You can use the $rename operator to change the name of a single field in a document.
{ "$rename": { "<Current Field Name>": <New Field Name>, ... } }
Increment a Value
You can use the $inc operator to add a specified number to the current value of a field. The number can be positive or negative.
{ "$inc": { "<Field Name>": <Increment Number>, ... } }
Multiply a Value
You can use the $mul operator to multiply a specified number with the current value of a field. The number can be positive or negative.
{ "$mul": { "<Field Name>": <Multiple Number>, ... } }
Array Update Operators
Array operators let you work with values inside of arrays.
Push an Element Into an Array
You can use the $push operator to add a value to the end of an array field.
{ "$push": { "<Array Field Name>": <New Array Element>, ... } }
Pop the Last Element out of an Array
You can use the $pop operator
to remove either the first or last element of an array field. Specify
-1
to remove the first element and 1
to remove the last element.
{ "$pop": { "<Array Field Name>": <-1 | 1>, ... } }
Add a Unique Element to an Array
You can use the $addToSet operator to add a value to an
array field if that value is not already included in the array. If the
value is already present, $addToSet
does nothing.
{ "$addToSet": { "<Array Field Name>": <Potentially Unique Value>, ... } }
Remove Elements from an Array
You can use the $pull operator to remove all instances of any values that match a specified condition from an array field.
{ "$pull": { "<Array Field Name>": <Value | Expression>, ... } }
Update All Elements in an Array
You can use the $[] (All Positional Update) operator to update all elements in an array field:
Example
Consider a students
collection that describes individual students in a
class. The documents each include a grades
field that contains an array
of numbers:
{ "_id" : 1, "grades" : [ 85, 82, 80 ] } { "_id" : 2, "grades" : [ 88, 90, 92 ] } { "_id" : 3, "grades" : [ 85, 100, 90 ] }
The following update operation adds 10 to all values in the grades
array
of every student:
await students.updateMany( {}, { $inc: { "grades.$[]": 10 } }, )
After the update, every grade value has increased by 10:
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 102 ] } { "_id" : 3, "grades" : [ 95, 110, 100 ] }
Update Specific Elements in an Array
You can use the $[element] (Filtered Positional Update) operator to update specific elements in an array field based on an array filter:
Example
Consider a students
collection that describes individual students in a
class. The documents each include a grades
field that contains an array
of numbers, some of which are greater than 100:
{ "_id" : 1, "grades" : [ 15, 92, 90 ] } { "_id" : 2, "grades" : [ 18, 100, 102 ] } { "_id" : 3, "grades" : [ 15, 110, 100 ] }
The following update operation sets all grade values greater than 100 to exactly 100:
await students.updateMany( { }, { $set: { "grades.$[grade]" : 100 } }, { arrayFilters: [{ "grade": { $gt: 100 } }] } )
After the update, all grade values greater than 100 are set to exactly 100 and all other grades are unaffected:
{ "_id" : 1, "grades" : [ 15, 92, 90 ] } { "_id" : 2, "grades" : [ 18, 100, 100 ] } { "_id" : 3, "grades" : [ 15, 100, 100 ] }
Delete
Delete operations find existing documents in a MongoDB collection and remove them. You use standard MongoDB query syntax to specify which documents to delete.
Delete a Single Document (deleteOne()
)
You can delete a single document from a collection using the
collection.deleteOne()
method.
The following Function snippet deletes one document
in the items
collection that has a name
value of 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}`))
Alternatively, you can update a single document using
collection.findOneAndDelete()
. This method allows you to
find, remove, and return the deleted document in a single operation.
Delete One or More Documents (deleteMany()
)
You can delete multiple items from a collection using the
collection.deleteMany()
method.
The following snippet deletes all documents in the items
collection
that do not have any 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}`))
Bulk Writes
A bulk write combines multiple write operations into a single operation.
You can issue a bulk write command using the
collection.bulkWrite()
method.
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}); };
Transactions
MongoDB supports multi-document transactions that let you read and write multiple documents atomically, even across collections.
To perform a transaction:
Obtain and start a client session with
client.startSession()
.Call
session.withTransaction()
to define the transaction. The method takes an async callback function and, optionally, a configuration object that defines custom read and write settings for the transaction.session.withTransaction(async () => { // ... Run MongoDB operations in this callback }, { readPreference: "primary", readConcern: { level: "local" }, writeConcern: { w: "majority" }, }) In the transaction callback function, run the MongoDB queries that you would like to include in the transaction. Be sure to pass the
session
to each query to ensure that it is included in the transaction.await accounts.updateOne( { name: userSubtractPoints }, { $inc: { browniePoints: -1 * pointVolume } }, { session } ); If the callback encounters an error, call
session.abortTransaction()
to stop the transaction. An aborted transaction does not modify any data.try { // ... } catch (err) { await session.abortTransaction(); } When the transaction is complete, call
session.endSession()
to end the session and free resources.try { // ... } finally { await session.endSession(); }
The following example creates two users, "henry" and "michelle", and a uses a transaction to move "browniePoints" between those users atomically:
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(); } }