Query Operations
Query and Scan operations for retrieving multiple items.
POST /api/v1/databases/{databaseId}/items/query
Section titled “POST /api/v1/databases/{databaseId}/items/query”Queries items by partition key with optional sort key conditions.
Request:
{ "partitionKey": "user#123", "sortKeyCondition": "begins_with:order#2024", "filterExpression": null, "limit": 20, "cursor": null, "scanForward": true}| Field | Type | Required | Description |
|---|---|---|---|
partitionKey | string | Yes | Partition key value to query |
sortKeyCondition | string | No | Sort key condition (see operators below) |
filterExpression | object | No | Additional filter after query |
limit | integer | No | Max items to return (default: 20) |
cursor | string | No | Pagination cursor from previous response |
scanForward | boolean | No | Sort direction, true = ascending (default: true) |
Response (200 OK):
{ "items": [ { "pk": "user#123", "sk": "order#2024-001", "data": { "total": 99.99 } } ], "nextCursor": "eyJsYXN0S2V5Ijo...", "count": 1, "scannedCount": 1}Sort Key Operators
Section titled “Sort Key Operators”| Operator | Format | Example | Description |
|---|---|---|---|
| Equals | =:value | =:profile | Exact match |
| Less than | <:value | <:2024-01-01 | Before value |
| Less than or equals | <=:value | <=:2024-01-01 | At or before value |
| Greater than | >:value | >:2024-01-01 | After value |
| Greater than or equals | >=:value | >=:2024-01-01 | At or after value |
| Begins with | begins_with:prefix | begins_with:order# | Prefix match |
| Between | between:low:high | between:2024-01-01:2024-12-31 | Range inclusive |
Examples
Section titled “Examples”// Get all orders for a user{ "partitionKey": "user#123", "sortKeyCondition": "begins_with:order#"}
// Get orders from 2024{ "partitionKey": "user#123", "sortKeyCondition": "between:order#2024-01-01:order#2024-12-31"}
// Get the user's profile{ "partitionKey": "user#123", "sortKeyCondition": "=:profile"}POST /api/v1/databases/{databaseId}/items/scan
Section titled “POST /api/v1/databases/{databaseId}/items/scan”Scans all items in the database. Use with caution on large datasets.
Request:
{ "filterExpression": null, "limit": 20, "cursor": null}Response: Same format as query response.
Pagination
Section titled “Pagination”Both Query and Scan support cursor-based pagination:
// First request{ "partitionKey": "user#123", "limit": 10}
// Response{ "items": [...], "nextCursor": "eyJsYXN0S2V5Ijo...", "count": 10}
// Next page{ "partitionKey": "user#123", "limit": 10, "cursor": "eyJsYXN0S2V5Ijo..."}When nextCursor is null, there are no more items.
Sort Direction
Section titled “Sort Direction”Control the order of results with scanForward:
// Ascending order (oldest first){ "partitionKey": "user#123", "sortKeyCondition": "begins_with:order#", "scanForward": true}
// Descending order (newest first){ "partitionKey": "user#123", "sortKeyCondition": "begins_with:order#", "scanForward": false}Code Examples
Section titled “Code Examples”// Query with sort key conditionvar filter = new QueryFilter{ PartitionKey = "user#123", SortKeyCondition = SortKeyCondition.BeginsWith("order#")};
var options = new QueryOptions{ Limit = 50, ScanForward = false // Descending order};
var result = await client.QueryAsync(filter, options);
if (result.IsSuccess){ foreach (var item in result.Value.Items) { Console.WriteLine($"Order: {item.SortKey}"); }
// Handle pagination if (result.Value.HasMore) { var nextPage = await client.QueryAsync(filter, new QueryOptions { NextToken = result.Value.NextToken }); }}
// Scan all itemsvar scanResult = await client.ScanAsync(new PaginationOptions{ Limit = 100});# Querycurl -X POST "https://api.terrascale.io/api/v1/databases/my-db/items/query" \ -H "Authorization: Bearer ts_live_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "partitionKey": "user#123", "sortKeyCondition": "begins_with:order#", "limit": 20 }'
# Scancurl -X POST "https://api.terrascale.io/api/v1/databases/my-db/items/scan" \ -H "Authorization: Bearer ts_live_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "limit": 100 }'Best Practices
Section titled “Best Practices”Use Query Instead of Scan
Section titled “Use Query Instead of Scan”Queries are efficient because they target a specific partition. Scans read the entire database.
// Good: Query by partition key{ "partitionKey": "user#123" }
// Avoid: Scan the whole database{}Design Keys for Access Patterns
Section titled “Design Keys for Access Patterns”Structure your keys to support your query patterns:
// Access pattern: Get all orders for a user{ "pk": "user#123", "sk": "order#2024-001" }
// Access pattern: Get orders by date{ "pk": "orders#2024-01", "sk": "user#123#order#001" }Limit Result Size
Section titled “Limit Result Size”Always specify a reasonable limit to avoid fetching too much data:
{ "partitionKey": "user#123", "limit": 50}Next Steps
Section titled “Next Steps”- Batch Operations - Bulk read operations
- Transactions - Consistent reads
- Best Practices - Query optimization