My personal notes
T

Azure Cosmos DB Pre-triggers and Post-triggers

Azure Cosmos DB supports pretriggers and post-triggers.

Triggers aren't automatically executed, they must be specified for each database operation where you want them to execute.

After you define a trigger, you should register it by using the Azure Cosmos DB SDKs.

Pre-triggers

Pretriggers are executed before modifying a database item. Pretriggers can't have any input parameters.

Here's an example of pre-trigger that manipulates the request message associated with the operation.

function validateToDoItemTimestamp() {
  var context = getContext();
  var request = context.getRequest();

  // item to be created in the current operation
  var itemToCreate = request.getBody();

  // validate properties
  if (!("timestamp" in itemToCreate)) {
    var ts = new Date();
    itemToCreate["timestamp"] = ts.getTime();
  }

  // update the item that will be created
  request.setBody(itemToCreate);
}

When triggers are registered, you can specify the operations that it can run with. For example, you can define that a trigger runs only before the creation of an element, and not during the update.

So, you first have to register the trigger:

await client
  .GetContainer("database", "container")
  .Scripts
  .CreateTriggerAsync(new TriggerProperties
  {
      Id = "trgPreValidateToDoItemTimestamp",
      Body = File.ReadAllText("@..\js\trgPreValidateToDoItemTimestamp.js"),
      TriggerOperation = TriggerOperation.Create,
      TriggerType = TriggerType.Pre
  });

Then, every time you execute an operation, you have to list the triggers to execute by specifying the ID.

dynamic newItem = new
{
    category = "Personal",
    name = "Groceries",
    description = "Pick up strawberries",
    isComplete = false
};

await client
  .GetContainer("database", "container")
  .CreateItemAsync(newItem, null, new ItemRequestOptions
  {
    PreTriggers = new List<string> { "trgPreValidateToDoItemTimestamp" }
  });

Post-triggers

Post-triggers are executed after modifying a database item.

The following trigger queries for the metadata item and updates it with details about the newly created item.

function updateMetadata() {
  var context = getContext();
  var container = context.getCollection();
  var response = context.getResponse();

  // item that was created
  var createdItem = response.getBody();

  // query for metadata document
  var filterQuery = 'SELECT * FROM root r WHERE r.id = "_metadata"';
  var accept = container.queryDocuments(
    container.getSelfLink(),
    filterQuery,
    updateMetadataCallback
  );

  if (!accept) throw "Unable to update metadata, abort";

  function updateMetadataCallback(err, items, responseOptions) {
    if (err) throw new Error("Error" + err.message);

    if (items.length != 1) throw "Unable to find metadata document";

    var metadataItem = items[0];

    // update metadata
    metadataItem.createdItems += 1;
    metadataItem.createdNames += " " + createdItem.id;
    var accept = container.replaceDocument(
      metadataItem._self,
      metadataItem,
      function (err, itemReplaced) {
        if (err) throw "Unable to update metadata, abort";
      }
    );

    if (!accept) throw "Unable to update metadata, abort";

    return;
  }
}

The post-trigger runs as part of the same transaction for the underlying item itself. An exception during the post-trigger execution fails the whole transaction. Anything committed is rolled back and an exception returned.

You have to register the trigger using the SDK:

await client
      .GetContainer("database", "container")
      .Scripts
      .CreateTriggerAsync(new TriggerProperties
      {
          Id = "trgPostUpdateMetadata",
          Body = File.ReadAllText(@"..\js\trgPostUpdateMetadata.js"),
          TriggerOperation = TriggerOperation.Create,
          TriggerType = TriggerType.Post
      });

Then you must specify the triggers to use when creating (or operating on) items.

var newItem = {
    name: "artist_profile_1023",
    artist: "The Band",
    albums: ["Hellujah", "Rotators", "Spinning Top"]
};

await client
      .GetContainer("database", "container")
      .CreateItemAsync(newItem, null,
      new ItemRequestOptions
      {
        PostTriggers = new List<string> { "trgPostUpdateMetadata" }
      });
Show Graph Visualisation