Skip to content

feat: add BETWEEN support for sort key conditions #17

@rauann

Description

@rauann

Summary

DynamoDB supports sk BETWEEN :low AND :high in KeyConditionExpression for sort keys. This is useful for range queries (e.g., date ranges, numeric ranges).

Current Behavior

Users can already express BETWEEN semantics via sk >= low and sk <= high in Ash filters — no new Ash function or fragment is needed. However, the current implementation has suboptimal handling:

  1. partition_predicates/2 removes both SK predicates from filter_preds (since they reference a key attribute)
  2. build_key_condition/4 calls fetch_key_value/2 which uses Enum.find_value — it only captures the first SK predicate for KeyConditionExpression
  3. The second SK predicate is not in KeyConditionExpression and not in FilterExpression — it's only caught by runtime filtering via apply_runtime_filter/2

This means queries like sk >= "2024-01-01" and sk <= "2024-12-31" currently:

  • Push only one condition (e.g., sk >= "2024-01-01") to KeyConditionExpression
  • Apply the other (e.g., sk <= "2024-12-31") as a runtime filter (client-side)
  • Return correct results, but read more items from DynamoDB than necessary

Recommended Implementation

  1. Detect complementary SK predicates — in build_key_condition/4, find two predicates on the same sort key with >= and <= operators, and emit #sk BETWEEN :v_sk_low AND :v_sk_high in KeyConditionExpression
  2. No new Ash function neededBETWEEN maps to existing >= and <= operators that Ash already supports
  3. Fallback — when only one SK predicate exists, keep the current single-operator behavior

Current vs. optimized behavior

Post
|> Ash.Query.filter(partition_key == "pk1" and sort_key >= "2024-01-01" and sort_key <= "2024-12-31")
|> Ash.read!()

Currently generates: KeyConditionExpression: "#pk = :v_pk AND #sk >= :v_sk" (second condition is runtime-only)
Would generate: KeyConditionExpression: "#pk = :v_pk AND #sk BETWEEN :v_sk_low AND :v_sk_high"

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions