Docs Menu

Write Data in MongoDB Atlas - Functions

On this page

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.

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.

The JSON schema for store.items
{
"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" }
}
}
}
}
}

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 operations take one or more documents and add them to a MongoDB collection.

They return documents that describe the results of the operation.

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}`))

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

Note

While running update operations, Atlas App Services temporarily adds a reserved field, _id__baas_transaction, to documents. If you modify data used by your app outside of App Services, you may need to unset this field. For more information, see Transactional Locks.

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}`))

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}`))

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 operators let you modify the fields and values of a document.

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>, ... } }

You can use the $rename operator to change the name of a single field in a document.

{ "$rename": { "<Current Field Name>": <New Field Name>, ... } }

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>, ... } }

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 operators let you work with values inside of arrays.

You can use the $push operator to add a value to the end of an array field.

{ "$push": { "<Array Field Name>": <New Array Element>, ... } }

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>, ... } }

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>, ... } }

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>, ... } }

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" : [ 15, 92, 90 ] }
{ "_id" : 2, "grades" : [ 18, 100, 102 ] }
{ "_id" : 3, "grades" : [ 15, 110, 100 ] }

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 operations find existing documents in a MongoDB collection and remove them. You use standard MongoDB query syntax to specify which documents to delete.

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}`))

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}`))

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});
};

MongoDB supports multi-document transactions that let you read and write multiple documents atomically, even across collections.

To perform a transaction:

  1. Obtain and start a client session with client.startSession().
  2. 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" },
    })
  3. 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 }
    );
  4. 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();
    }
  5. 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();
}
}
←  Read Data from MongoDB Atlas - FunctionsAggregate Data in MongoDB Atlas - Functions →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.