Azure Cosmos DB

JavaScript SDK Documentation

Introduction to the Azure Cosmos DB JavaScript SDK

Welcome to the official documentation for the Azure Cosmos DB JavaScript SDK. This SDK provides a high-level, object-oriented interface for interacting with your Azure Cosmos DB resources from your JavaScript applications.

Azure Cosmos DB is a globally distributed, multi-model database service that enables you to read and write data at lightning speed. The JavaScript SDK simplifies common operations such as creating, reading, updating, and deleting data, as well as querying your data using SQL or other supported query languages.

This documentation will guide you through installing, configuring, and using the SDK effectively, covering essential concepts and common use cases.

Installation

You can install the Azure Cosmos DB JavaScript SDK using npm or yarn. We recommend using it within a Node.js environment.

npm install @azure/cosmos

Or using yarn:

yarn add @azure/cosmos

Getting Started

To start using the SDK, you need to import the `CosmosClient` and initialize it with your Cosmos DB account's endpoint and primary key.


import { CosmosClient } from "@azure/cosmos";

const endpoint = "YOUR_COSMOS_DB_ENDPOINT";
const key = "YOUR_COSMOS_DB_PRIMARY_KEY";

const client = new CosmosClient({ endpoint, key });

async function runDemo() {
    // Your database and container operations will go here
    console.log("CosmosClient initialized successfully.");
}

runDemo().catch(error => {
    console.error("Error:", error);
});
                

Client Configuration

The `CosmosClient` constructor accepts an optional configuration object. This object can include options for:

  • endpoint: The URI of your Cosmos DB account.
  • key: The primary or secondary read-write key for your account.
  • connectionPolicy: Configure aspects like retry policies, timeouts, and consistency levels.
  • userAgentSuffix: A string to append to the User-Agent header for analytics.

Connection Policy Options

The `connectionPolicy` object allows fine-grained control over network and retry behavior:

  • requestTimeout: The maximum time in milliseconds to wait for a request to complete.
  • mediaReadTimeout: The maximum time in milliseconds to wait for media content to be read.
  • retryOptions: Defines retry behavior for transient failures.

Database Operations

You can manage databases within your Cosmos DB account.

Create Database


async function createDatabase(databaseId) {
    const { database } = await client.databases.create({ id: databaseId });
    console.log(`Database ${database.id} created.`);
    return database;
}
                

Read Database


async function readDatabase(databaseId) {
    const { database } = await client.databases.read(databaseId);
    console.log(`Reading database: ${database.id}`);
    return database;
}
                

List Databases


async function listDatabases() {
    const { resources: databases } = await client.databases.list();
    console.log("Databases:");
    databases.forEach(db => console.log(`- ${db.id}`));
}
                

Container Operations

Containers are where your items (documents, rows, etc.) are stored. They require a partition key definition.

Create Container


async function createContainer(databaseId, containerId, partitionKeyPath) {
    const { database } = await client.databases.createIfNotExists({ id: databaseId });
    const { container } = await database.containers.createIfNotExists({
        id: containerId,
        partitionKey: {
            paths: [partitionKeyPath]
        }
    });
    console.log(`Container ${container.id} created in database ${database.id}.`);
    return container;
}
                

Read Container


async function readContainer(databaseId, containerId) {
    const { database } = await client.databases.read(databaseId);
    const { container } = await database.containers.read(containerId);
    console.log(`Reading container: ${container.id}`);
    return container;
}
                

List Containers


async function listContainers(databaseId) {
    const { database } = await client.databases.read(databaseId);
    const { resources: containers } = await database.containers.list();
    console.log(`Containers in ${databaseId}:`);
    containers.forEach(container => console.log(`- ${container.id}`));
}
                

Item Operations

Items are the actual data stored within a container. They are typically JSON documents.

Create Item

To create an item, you need to provide the item's content and its partition key value.


async function createItem(container, newItem) {
    const { resource: createdItem } = await container.items.create(newItem);
    console.log(`Created item with id: ${createdItem.id}`);
    return createdItem;
}

// Example item structure
const myItem = {
    id: "unique-item-id-123",
    name: "Example Item",
    category: "Electronics",
    price: 199.99,
    tags: ["sample", "test"]
};
                

Read Item

Retrieve an item using its unique ID and partition key value.


async function readItem(container, itemId, partitionKeyValue) {
    const { resource: item } = await container.item(itemId, partitionKeyValue).read();
    console.log(`Read item: ${item.id}`);
    return item;
}
                

Update Item

Update an existing item. You can either replace the entire item or partially update it using the `replace` method.


async function updateItem(container, itemId, partitionKeyValue, updatedProperties) {
    // Fetch the existing item first to ensure we have the latest version and _etag
    const { resource: existingItem } = await container.item(itemId, partitionKeyValue).read();

    // Merge updated properties into the existing item
    const updatedItemData = { ...existingItem, ...updatedProperties };

    const { resource: replacedItem } = await container.item(itemId, partitionKeyValue).replace(updatedItemData);
    console.log(`Updated item with id: ${replacedItem.id}`);
    return replacedItem;
}

// Example update
const updateData = { price: 219.99, description: "Updated price for the example item." };
                

Delete Item

Remove an item from the container.


async function deleteItem(container, itemId, partitionKeyValue) {
    await container.item(itemId, partitionKeyValue).delete();
    console.log(`Deleted item with id: ${itemId}`);
}
                

Query Items

The SDK supports querying items using a SQL-like query language. You can use `container.items.query()`.


async function queryItems(container, querySpec) {
    const { resources: results } = await container.items.query(querySpec).fetchAll();
    console.log("Query Results:");
    results.forEach(item => console.log(`- ${item.id}`));
    return results;
}

// Example query: Find all items in the 'Electronics' category with a price less than 200
const query = {
    query: "SELECT * FROM c WHERE c.category = @category AND c.price < @price",
    parameters: [
        { name: "@category", value: "Electronics" },
        { name: "@price", value: 200 }
    ]
};

// To execute:
// queryItems(myContainer, query);
                

Partition Keys

Partition keys are crucial for distributing your data and ensuring scalability. When creating or modifying containers, you must define a partition key path.

For single-key partition keys, the `partitionKey` object looks like this:


{
    kind: "Hash", // or "Range"
    paths: ["/yourPartitionKey"]
}
                

When performing operations on items (like creating, reading, updating, deleting), you must provide the corresponding partition key value for that item.

Transactions

Azure Cosmos DB supports ACID transactions across multiple items within a single logical partition using stored procedures or via the SDK's transaction capabilities (e.g., using the `executeSql` method with a stored procedure).

Change Feed

The change feed provides a persistent, ordered list of modifications to your items. You can process these changes in near real-time.


async function processChangeFeed(container) {
    const feedIterator = await container.items.getChangeFeedIterator({
        startFromBeginning: true,
        partitionKey: "yourPartitionKeyValue" // Optional: specify a partition key
    });

    while (feedIterator.hasMoreResults()) {
        const response = await feedIterator.fetchNext();
        response.resources.forEach(change => {
            console.log("Change detected:", change);
        });
    }
}
                

Bulk Operations

For performance-sensitive scenarios involving many operations, consider using the bulk operations API. This allows you to send multiple create, upsert, or delete requests in a single network call.


async function bulkOperations(container, operations) {
    const response = await container.items.bulk(operations);
    console.log("Bulk operation results:", response);
    return response;
}

// Example operations array:
// const bulkOps = [
//     { operationType: "Create", resourceBody: { id: "bulk-item-1", name: "Bulk Item One" } },
//     { operationType: "Upsert", resourceBody: { id: "bulk-item-2", name: "Bulk Item Two Updated" } },
//     { operationType: "Delete", id: "bulk-item-3", partitionKey: "pkValue" }
// ];
                

Error Handling

The SDK throws errors for various issues. It's essential to implement robust error handling, especially for network issues or conflicts.

Common Error Status Codes:

  • 409 Conflict: Indicates a conflict, often due to concurrent updates or duplicate IDs.
  • 429 Too Many Requests: Rate limiting has been applied. Implement retry logic.
  • 404 Not Found: The requested resource does not exist.

try {
    await container.item("non-existent-id", "pkValue").read();
} catch (error) {
    if (error.code === 404) {
        console.log("Item not found.");
    } else {
        console.error("An unexpected error occurred:", error);
    }
}
                

Advanced Topics

This documentation covers the fundamentals. For more advanced scenarios, explore:

  • Stored Procedures and User-Defined Functions (UDFs): For complex server-side logic.
  • Triggers: Pre- and post-operation logic execution.
  • Indexing Policies: Customizing how Cosmos DB indexes your data for query performance.
  • Geospatial Queries: Storing and querying location-based data.
  • Multi-region Writes: Configuring your database for high availability and low latency globally.

Refer to the official Azure documentation for comprehensive details and the latest updates.