Skip to main content

ORM For Dynamodb

Project description

Dynamojo


:exclamation: Important Notice :exclamation:

Version 1.0.0 is an important update that introduces breaking changes:

  • Pydantic dependency is now at 2.x
    • DynamojoBase._config attribute is now an abstractclassmethod named DynamojoBase.__config()
    • DynamojoBase._config must be declared in subclasses of DynamojoBase and must return a DynamojoConfig object
  • The following methods are now async:
    • DynamojoBase.delete
    • DynamojoBase.fetch
    • DynamojoBase.query
    • DynamojoBase.save
    • DynamojoBase.update

Because one table is better than more

Dynamojo takes the concept of Dynamodb Single Table design and creates a modeling framework for it. This library is opinionated in the following ways:

  • Indexes should be generic. They could mean different things for different types of items. An index attribute shouldn't imply that it is always a date, color, etc.
  • When using generic indexes the attributes should shadow a human readable attribute. For instance if you have a partition key named "pk" that for items that represent users stores their userid, then there should also be an attribute named userid.
  • When creating models for item types that will be stored in the database the developer should only have to worry about their access patterns in terms of the human readable attributes, not be in the weeds of the index design of the table. Mapping items to indexes should happen in code, not in the table definition itself
  • Table and Global Secondary indexes should always define a sortkey. There is no reason not to. It's better to have it in cases where you don't need it than to need it and not have it.

Dynamojo is built on top of Pydantic with some bells and whistles:

  • put, update, delete, and query db objects
  • Dynamically map attributes to the index of your choice. EG: attribute "userId" automatically populates the partition key named "pk"
  • Dynamically join attributes into another using a delimiter. For instance create a field that is <userid>~<date>~<action> to use as a sort key for fast queries
  • Mutate attributes when set
  • Create models that subclass other models. A common pattern is to define a base class for your project that has a baseline of methods that you will need other than db operations. Different item types would then be created as models that are subclasses from the base class. See test.py
  • Flag attributes as immutable so they can't be modified once set
  • Use all of the features of put_item(), query(), delete(), and update() that you normally could with boto3.client("dynamodb")

Limitations:

  • Dynamojo doesn't do scans because scans are dumb. I will die on the hill of defending that statement.
  • If you have so much data that replicating indexed data into human readable columns is too expensive then this library may not be for you. But if you have that much data you should have a staff of engineers that can write your own library.

See test.py for examples

This library is very opinionated about how the table's indexes should be structured. Below is Terraform that shows the correct way to set up the table. Index keys are never referenced directly when using the table. Rely on IndexMap for that. Since LSI's can only be created at table creation time, and all indexes cost nothing if not used, we go ahead and create all of the indexes that AWS will allow us to when the table is created.

resource "aws_dynamodb_table" "test_table" {
  name         = "test-dynamojo"
  hash_key     = "pk"
  range_key    = "sk"
  billing_mode = "PAY_PER_REQUEST"

  # LSI attributes
  dynamic "attribute" {
    for_each = range(5)

    content {
      name = "lsi${attribute.value}_sk"
      type = "S"
    }
  }

  # GSI pk attributes
  dynamic "attribute" {
    for_each = range(20)

    content {
      name = "gsi${attribute.value}_pk"
      type = "S"
    }
  }

  # GSI sk attributes
  dynamic "attribute" {
    for_each = range(20)

    content {
      name = "gsi${attribute.value}_sk"
      type = "S"
    }
  }

  attribute {
    name = "pk"
    type = "S"
  }

  attribute {
    name = "sk"
    type = "S"
  }

  # GSI's
  dynamic "global_secondary_index" {
    for_each = range(20)

    content {
      name            = "gsi${global_secondary_index.value}"
      hash_key        = "gsi${global_secondary_index.value}_pk"
      range_key       = "gsi${global_secondary_index.value}_sk"
      projection_type = "ALL"
    }
  }

  # LSI's
  dynamic "local_secondary_index" {
    for_each = range(5)

    content {
      name            = "lsi${local_secondary_index.value}"
      range_key       = "lsi${local_secondary_index.value}_sk"
      projection_type = "ALL"
    }
  }
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dynamojo-1.0.3.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

dynamojo-1.0.3-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file dynamojo-1.0.3.tar.gz.

File metadata

  • Download URL: dynamojo-1.0.3.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/23.1.0

File hashes

Hashes for dynamojo-1.0.3.tar.gz
Algorithm Hash digest
SHA256 578dde2b17c562a8fbea4e147f0a5b8ad4d799ceaba3adde2c7b1564dabcb60c
MD5 da7c6a47bb2b44a52e4105493d1bcca9
BLAKE2b-256 b2a922a5656649635a2f9681d52c3889301d30a5490c18ea2649dd08971e7adb

See more details on using hashes here.

File details

Details for the file dynamojo-1.0.3-py3-none-any.whl.

File metadata

  • Download URL: dynamojo-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/23.1.0

File hashes

Hashes for dynamojo-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 8316b4a26a035a86fec06c2240812c0ef26da9ff8bbaa3cfd5c1cb351f8ed7c7
MD5 12024749b8baaa3027e757ba5ec462b3
BLAKE2b-256 68d18b377fc2dc0e955853e625a3f623dc3c879ea61f67607427a042588e580a

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page