-
Notifications
You must be signed in to change notification settings - Fork 0
Expressions: Condition builder
buildCondition(clauses, params?) builds a DynamoDB ConditionExpression from a declarative clause tree. Composable with the other expression builders — names and value placeholders get unique aliases that don't collide with buildUpdate / addProjection / buildSearch.
See also (AWS JS SDK v3): Condition expressions · Expression attribute names ·
PutCommand/UpdateCommand/DeleteCommand. Vocabulary: Concepts.
buildCondition is an additive builder — same contract as Update builder → Additive builders. It appends to whatever ConditionExpression is already on params by AND-joining, so you can call it multiple times, and it interleaves freely with buildUpdate, buildSearch, and addProjection.
import {buildCondition} from 'dynamodb-toolkit/expressions';
const params = buildCondition([
{path: 'status', op: '=', value: 'active'},
{op: 'or', clauses: [
{path: 'priority', op: '>', value: 5},
{path: 'tags', op: 'contains', value: 'urgent'}
]}
]);
// ConditionExpression: "#cd0 = :cdv0 AND (#cd1 > :cdv1 OR contains(#cd2, :cdv2))"type ConditionClause =
| {path: string; op: '=' | '<>' | '<' | '<=' | '>' | '>='; value: unknown}
| {path: string; op: 'exists' | 'notExists'}
| {path: string; op: 'beginsWith' | 'contains'; value: unknown}
| {path: string; op: 'in'; value: unknown[]} // `values` still accepted as a legacy alias
| {op: 'and' | 'or'; clauses: ConditionClause[]}
| {op: 'not'; clause: ConditionClause};The top-level clauses array is AND-joined. To mix OR at the top level, wrap explicitly:
buildCondition([{op: 'or', clauses: [...]}]);Paths use the same dotted-segment convention as the Update builder — pure-digit segments become array indices, dotted paths nest into maps:
buildCondition([{path: 'config.thresholds.0', op: '>=', value: 10}]);
// ConditionExpression: "#cd0.#cd1[0] >= :cdv0"The put / patch / delete methods accept a conditions option that's fed straight to buildCondition:
await adapter.put(item, {
conditions: [
{path: 'version', op: '=', value: 3},
{path: 'locked', op: 'notExists'}
]
});
// Guarded delete — see Adapter: CRUD methods → delete
await adapter.delete({name: 'Hoth'}, {
conditions: [{path: 'status', op: '=', value: 'archived'}]
});The conditions are added on top of any existing attribute_exists / attribute_not_exists checks the Adapter applies (e.g., for post). See Adapter: CRUD methods for the delete guard pattern and Adapter: Hooks updateInput for the broader "insert a cross-cutting condition" story.
For one-off conditions the builder doesn't cover — DynamoDB functions like size(), attribute_type(), complex precedence — use the updateInput hook to add the raw expression after the builder runs:
hooks: {
updateInput(input, op) {
if (op.name === 'put') {
input.ConditionExpression = `(${input.ConditionExpression}) AND size(#tags) < :cap`;
input.ExpressionAttributeNames['#tags'] = 'tags';
input.ExpressionAttributeValues[':cap'] = 100;
}
return input;
}
}Start here
- Getting started
- Concepts
- Key and field design
- Compatibility
- Migration: v2 to v3
- SDK v2 to v3 cheat sheet
Guides
- Hierarchical data walkthrough
- Key expression patterns
- Multi-type tables
- Pagination
- Mass operation semantics
- URL schema design
Adapter
- Adapter
- Constructor options
- CRUD methods
- Mass methods
- Batch builders
- Hooks
- Raw marker
- Indirect indices
- Transaction auto-upgrade
Expression builders
Batch / transactions / mass / paths
REST surface
Framework adapters
Recipes
- Recipes index
- List records of a tier
- Per-tier sparse GSI markers
- Tier within a partition
- Reservation with auto-release
- Keys-only GSI, runtime projection
- Cascade subtree operations
- Querying subtrees with buildKey
- Filter URL grammar
- Text search
- Provisioning workflow
- Resumable mass operations
History