Dung (Donny) Nguyen

Senior Software Engineer

Inserting and Querying with Partition Key and Sort Key

Below is a clean, practical guide to inserting and querying items in DynamoDB when your table uses a partition key + sort key. This fits naturally with the table you created earlier (userId as HASH, createdAt as RANGE).


Inserting Items (PutItem)

You can insert items using PutItemCommand from AWS SDK v3.

import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";

const client = new DynamoDBClient({ region: "us-east-1" });

async function insertUserEvent() {
  const command = new PutItemCommand({
    TableName: "Users",
    Item: {
      userId: { S: "123" },
      createdAt: { S: new Date().toISOString() },
      action: { S: "LOGIN" },
      ip: { S: "192.168.1.10" }
    }
  });

  await client.send(command);
  console.log("Item inserted");
}

insertUserEvent();

Notes


Querying Items by Partition Key

To fetch all items for a given user:

import { QueryCommand } from "@aws-sdk/client-dynamodb";

async function getUserEvents(userId) {
  const command = new QueryCommand({
    TableName: "Users",
    KeyConditionExpression: "userId = :uid",
    ExpressionAttributeValues: {
      ":uid": { S: userId }
    }
  });

  const result = await client.send(command);
  return result.Items;
}

getUserEvents("123").then(console.log);

What this does


Querying by Partition Key + Sort Key Range

This is where sort keys shine.

Example: Get events between two timestamps

async function getEventsInRange(userId, start, end) {
  const command = new QueryCommand({
    TableName: "Users",
    KeyConditionExpression: "userId = :uid AND createdAt BETWEEN :start AND :end",
    ExpressionAttributeValues: {
      ":uid": { S: userId },
      ":start": { S: start },
      ":end": { S: end }
    }
  });

  const result = await client.send(command);
  return result.Items;
}

getEventsInRange(
  "123",
  "2025-01-01T00:00:00Z",
  "2025-01-02T00:00:00Z"
).then(console.log);

Querying with begins_with (prefix search)

Useful for time‑series data if you store timestamps like 2025-01-01T....

async function getEventsForDay(userId, dayPrefix) {
  const command = new QueryCommand({
    TableName: "Users",
    KeyConditionExpression: "userId = :uid AND begins_with(createdAt, :day)",
    ExpressionAttributeValues: {
      ":uid": { S: userId },
      ":day": { S: dayPrefix } // e.g. "2025-01-01"
    }
  });

  const result = await client.send(command);
  return result.Items;
}

getEventsForDay("123", "2025-01-01").then(console.log);

Querying in Descending Order

By default, DynamoDB sorts ascending. To reverse:

const command = new QueryCommand({
  TableName: "Users",
  KeyConditionExpression: "userId = :uid",
  ExpressionAttributeValues: {
    ":uid": { S: "123" }
  },
  ScanIndexForward: false // descending
});

Querying Only the Latest Item

This is extremely common (e.g., latest login event):

const command = new QueryCommand({
  TableName: "Users",
  KeyConditionExpression: "userId = :uid",
  ExpressionAttributeValues: {
    ":uid": { S: "123" }
  },
  ScanIndexForward: false, // newest first
  Limit: 1
});