Database Triggers
On this page
Overview
Database Triggers allow you to execute server-side logic whenever a document is added, updated, or removed in a linked MongoDB Atlas cluster. You can use database Triggers to implement complex data interactions, including updating information in one document when a related document changes or interacting with a service upon the insertion of a new document.
Database Triggers use MongoDB change streams to listen for changes to documents in a collection and pass database events to their associated Trigger function.
You can use a $match expression document to filter change events based on field values. For more information, see Query on Embedded Documents in the MongoDB server manual.
Atlas App Services opens a single change stream for each collection with at least one enabled Trigger and limits the total number of open change streams on each linked cluster across all Apps based on the cluster's size. See change stream limitations for more information.
Database Triggers are only available for MongoDB Atlas clusters running MongoDB version 3.6 or newer.
You cannot define a database trigger on a serverless instance or data lake.
Example
An online store wants to notify its customers whenever one of their
orders changes location. They record each order in the store.orders
collection as a document that resembles the following:
{ _id: ObjectId("59cf1860a95168b8f685e378"), customerId: ObjectId("59cf17e1a95168b8f685e377"), orderDate: ISODate("2018-06-26T16:20:42.313Z"), shipDate: ISODate("2018-06-27T08:20:23.311Z"), orderContents: [ { qty: 1, name: "Earl Grey Tea Bags - 100ct", price: NumberDecimal("10.99") } ], shippingLocation: [ { location: "Memphis", time: ISODate("2018-06-27T18:22:33.243Z") }, ] }
To automate this process, the store creates a database Trigger that
listens for UPDATE
change events in the store.orders
collection.
When the trigger observes an UPDATE
event, it passes the
change event object to its associated Function,
textShippingUpdate
. The Function checks the change event for any
changes to the shippingLocation
field and, if it was updated, sends
a text message to the customer with the new location of the order.
exports = async function (changeEvent) { // Destructure out fields from the change stream event object const { updateDescription, fullDocument } = changeEvent; // Check if the shippingLocation field was updated const updatedFields = Object.keys(updateDescription.updatedFields); const isNewLocation = updatedFields.some(field => field.match(/shippingLocation/) ); // If the location changed, text the customer the updated location. if (isNewLocation) { const { customerId, shippingLocation } = fullDocument; const twilio = context.services.get("myTwilioService"); const mongodb = context.services.get("mongodb-atlas"); const customers = mongodb.db("store").collection("customers"); const { location } = shippingLocation.pop(); const customer = await customers.findOne({ _id: customer_id }) twilio.send({ to: customer.phoneNumber, from: context.values.get("ourPhoneNumber"), body: `Your order has moved! The new location is ${location}.` }); } };
Configuration
Database Triggers have the following configuration options:
Field | Description |
---|---|
Trigger Type | Required. The type of the Trigger. Set this value to DATABASE for database Triggers |
Trigger Name | Required. The name of the Trigger. |
Linked Function | Required. The name of the App Services Function that the Trigger
executes whenever it fires. The Trigger passes the
database event object that
caused it to fire as the only argument to this Function. |
Cluster | Required. The name of the MongoDB Service that the Trigger is
associated with. |
Database Name | Required. The MongoDB database that contains the watched
collection. |
Collection Name | Required. The name of the collection that the Trigger watches for
change events. |
Operation Types | Required. A list of one or more database operation
types that cause the Trigger to
fire. Format each operation type as an uppercase string, e.g.,
Warning Update operations executed from MongoDB Compass or the MongoDB Atlas
Data Explorer fully replace the previous document. As a result,
update operations from these clients will generate |
Full Document | If enabled, Note Regardless of this setting:
|
Document Preimage | If enabled, change events include a copy of the modified document
from immediately before the change was applied in the
Tip Performance Optimization Disable preimages at a collection level to improve performance. Learn more. |
Event Ordering | If event ordering is enabled, multiple executions of this Trigger will occur sequentially based on the timestamps of the change events. If event ordering is disabled, multiple executions of this Trigger will occur independently. Tip Performance Optimization Improve performance for Triggers that respond to bulk database operations by disabling event ordering. Learn more. |
Match Expression | Optional. A $match expression document
that App Services uses to filter which change events cause the Trigger to
fire. The Trigger evaluates all change event objects that it receives against
this match expression and only executes if the expression evaluates to Note Use Dot-Notation for Embedded Fields MongoDB performs a full equality match for embedded documents in a match expression. If you want to match a specific field in an embedded document, refer to the field directly using dot-notation. For more information, see Query on Embedded Documents in the MongoDB server manual. Tip Performance Optimization Limit the number of fields that the Trigger processes by using a $match expression. Learn more. |
Project Expression | Optional. A $project expression document that App Services uses to filter the fields that appear in change event objects. Tip Performance Optimization Limit the number of fields that the Trigger processes by using a $project expression. Learn more. |
Database Change Events
Database change events represent individual changes in a specific collection of your linked MongoDB Atlas cluster.
Every database event has the same operation type and structure as the change event object that was emitted by the underlying change stream. Change events have the following operation types:
Operation Type | Description |
---|---|
INSERT | Represents a new document added to the collection. |
UPDATE | Represents a change to an existing document in the collection. |
REPLACE | Represents a new document that replaced a document in the collection. |
DELETE | Represents a document deleted from the collection. |
Database change event objects have the following general form:
{ _id : <ObjectId>, "operationType": <string>, "fullDocument": <document>, "fullDocumentBeforeChange": <document>, "ns": { "db" : <string>, "coll" : <string> }, "documentKey": { "_id": <ObjectId> }, "updateDescription": <document>, "clusterTime": <Timestamp> }
Suspended Triggers
Database Triggers may enter a suspended state in response to an event that prevents the Trigger's change stream from continuing. Events that can suspend a Trigger include:
- invalidate events
such as
dropDatabase
,renameCollection
, or those caused by a network disruption - the token required to resume the change stream is no longer in the cluster oplog
- importing an App with the
replace
strategy instead of themerge
strategy and consequently removing the database user that created the Trigger's change stream
When resuming the suspended Trigger, App Services attempts to resume the Trigger at the next change stream event after the change stream stopped. However, if the resume token is no longer in the cluster oplog, the Trigger begins listening to new events but does not process any missed past events.
You can adjust the oplog size to keep the resume token for more time after a suspension by scaling your Atlas cluster. Maintain an oplog size a few times greater than your cluster's peak oplog throughput (GB/hour) to reduce the risk of a suspended trigger's resume token dropping off the oplog before the trigger executes. View your cluster's oplog throughput in the Oplog GB/Hour graph in the Atlas cluster metrics.
Last Cluster Time Processed
All Triggers keep track of the last time the Trigger executed, known as the latest execution in the Atlas App Services UI. Database Triggers also keep track of the last cluster time processed: the last time the change stream backing that Trigger emitted an event. You can access these timestamps in the list of Triggers that displays when you first navigate to the Triggers section from the sidebar.
The difference between the latest execution and the last cluster time processed represents the latency between when an event occurs in your database, and when the Trigger finishes responding to that event. If latency is consistently large, you can reduce it with the following mitigations:
- Optimize the Trigger's Linked Function to speed up execution.
- If your Trigger uses Event Ordering, consider switching ordering off to reduce latency.
- Add resources by upgrading your MongoDB Atlas cluster.
Performance Optimization
Disable Event Ordering for Burst Operations
Consider disabling event ordering if your trigger fires on a collection that receives short bursts of events (e.g. inserting data as part of a daily batch job).
Ordered Triggers wait to execute a Function for a particular event until the Functions of previous events have finished executing. As a consequence, ordered Triggers are effectively rate-limited by the run time of each sequential Trigger function. This may cause a significant delay between the database event and the Trigger firing if a sufficiently large number of Trigger executions are currently in the queue.
Unordered Triggers execute functions in parallel if possible, which can be significantly faster (depending on your use case) but does not guarantee that multiple executions of a Trigger Function occur in event order.
Disable Collection-Level Preimages
Document preimages use extra information stored in the oplog. The extra data may degrade trigger performance.
Once you've enabled document preimages for any trigger on a given collection, that collection will include preimage data in the oplog and other triggers on the collection can use preimages with no additonal overhead.
You can disable document preimages on a per-trigger basis to exclude the preimage from change events. Regardless of your trigger-level settings, a collection's oplog entries will continue to include preimage data unless you explicitly disable preimages for the collection.
Use Match Expressions to Limit Trigger Invocations
In the Match Expression field, limit the number of Trigger invocations by using Match expressions. The Trigger is only invoked if the document meets the criteria of the $match expression.
The following Match Expression configures a trigger to fire only
if the change event object specifies that the status
field in a document
changed.
{ "updateDescription.updatedFields.status": { "$exists": true } }
Use Project Expressions to Reduce Input Data Size
In the Project Expression field, limit the number of fields that the Trigger processes by using a $project expression.
When using Triggers, a projection expression is inclusive only.
Project does not support mixing inclusions and exclusions.
The project expression must be inclusive because Triggers require you
to include operationType
.
If you want to exclude a single field, the projection expression must
include every field except the one you want to exclude.
You can only explicitly exclude _id
, which is included by default.
A trigger is configured with the following Project Expression:
{ "_id": 0, "operationType": 1, "updateDescription.updatedFields.status": 1 }
The change event object that App Services passes to the trigger function only includes the fields specifed in the projection, as in the following example:
{ "operationType": "update", "updateDescription": { "updatedFields": { "status": "InProgress" } } }