Azure Cosmos DB Documentation

Creating Custom JavaScript Triggers in Azure Cosmos DB

This tutorial guides you through the process of creating and implementing custom JavaScript triggers in Azure Cosmos DB. Triggers allow you to execute server-side logic automatically when specific events occur on your data.

What are Cosmos DB Triggers?

Cosmos DB supports pre- and post-operation triggers written in JavaScript. These triggers can be executed before or after document creation, updates, or deletions. They are invaluable for enforcing data consistency, performing complex validation, or performing related actions without client-side intervention.

  • Pre-triggers: Execute before the operation. Useful for validation or data transformation.
  • Post-triggers: Execute after the operation. Useful for auditing or initiating follow-up actions.

Prerequisites

Before you begin, ensure you have the following:

  • An Azure account.
  • An Azure Cosmos DB account with a database and a container.
  • Azure Cosmos DB emulator installed (optional, for local development).
  • An application or tool to interact with your Cosmos DB data (e.g., Azure portal, SDK).

Creating a JavaScript Trigger

You can create triggers through the Azure portal or using the Cosmos DB SDKs. Here's how using the Azure portal:

  1. Navigate to your Azure Cosmos DB account in the Azure portal.
  2. Select your database and then your container.
  3. In the container's menu, under "Programmability", select "Triggers".
  4. Click "Add Trigger".
  5. Fill in the trigger details:
    • Name: A unique name for your trigger (e.g., validateItemOnCreate).
    • Type: Select either Pre or Post.
    • Operation: Select the operation(s) this trigger should respond to (e.g., Create, Update, Delete).
    • Script: Write your JavaScript code in the provided editor.
  6. Click "OK" to save the trigger.

Example: A Pre-trigger for Data Validation

Let's create a pre-trigger that validates if a new item has a required name property before it's created.

Trigger Code:

function validateItemOnCreate() {
    var item = getContext().getRequest().getBody();

    if (item.name === undefined || item.name === null || item.name === "") {
        throw new Error("The 'name' property is required and cannot be empty.");
    }

    if (item.quantity === undefined || typeof item.quantity !== 'number' || item.quantity < 0) {
        throw new Error("The 'quantity' property must be a non-negative number.");
    }

    // Accept the document if validation passes
    getContext().getRequest().setBody(item);
}

Explanation:

  • The getContext().getRequest().getBody() function retrieves the document being processed.
  • The script checks if the name and quantity properties exist and meet certain criteria.
  • If validation fails, an Error is thrown, which prevents the operation from completing and returns an error message to the client.
  • If validation succeeds, getContext().getRequest().setBody(item) ensures the document is passed along for the actual operation.

Important: Always ensure your trigger script handles potential errors gracefully and throws meaningful exceptions when necessary.

Executing the Trigger

Once the trigger is created, it will automatically execute when you perform the specified operation on a document. For example, if you try to create a document without the name property using a client SDK or the Data Explorer in the Azure portal, the trigger will fire, and the operation will fail with the error message defined in the script.

Example of triggering the validation (Conceptual - requires SDK usage):

If you attempt to create an item like this:

{
    "id": "some-id",
    "price": 10.99
}

The validateItemOnCreate trigger will intercept this request, and you'll receive an error similar to: "The 'name' property is required and cannot be empty."

Common Use Cases

  • Data Validation: Enforcing schema compliance and business rules before data is committed.
  • Data Transformation: Modifying incoming data, such as adding timestamps or normalizing fields.
  • Auditing: Logging changes or metadata related to data operations.
  • Complex Calculations: Performing calculations based on document content that might be too complex for client applications.

Best Practices

  • Keep trigger logic concise and focused.
  • Handle errors properly and provide informative error messages.
  • Test triggers thoroughly in a development or staging environment before deploying to production.
  • Be mindful of performance; complex or slow triggers can impact your application's responsiveness.
  • Consider idempotency if your triggers might be re-executed.