Models - mavills/single-table-orm GitHub Wiki

DynamoDB table setup

The table name is read from the environment variable DB_TABLE_NAME. If you need another way of setting the table name (e.g. dynamically), either set the variable in code, or directly adapt the connection manager variable table.

Only one setup of table is supported, accessible through the table_config:

  • The primary key is called PK
  • The sort key is called SK
  • There is a Global Secondary Index called GSI1
  • The primary key of the GSI is called GSI1PK
  • The sort key is also SK (overlapping sort key)

Model definitions

Models represent types of objects you can store in DynamoDB. It is best explained using examples.

PK SK GSI1PK tenant_name integration_id locked last_seen_run enabled notebook_path created_on static_files dynamic_files
T#tenant-2#Integrations I#INT0001 crusty-crab-tenant INT0001 TRUE run_21901 TRUE s3://buckentname/notebooks/... 17000000 [...] [...]

In this example, we represent an integration for a specific tenant. The integration has a tenant name and integration, which define the PK and SK.

The PK is constructed from taking all class attribute names marked as PK, concatinating them, and applying the suffix. Here are some examples:

class Fruit:
  apple = Field(str, pk=True)
  banana = Field(str, pk=True)
  coconut = Field(str, pk=True)
  date = Field(str)

>>> A().get_pk()
... A#<value_of_apple>#B#<value_of_banana>#C#<value_of_coconut>#Fruit

As you can see, the class name is added as suffix. You can change this suffix using the meta class:

class Fruit:
  apple = Field(str, pk=True)
  
  class Meta:
    suffix = "RedFruit"

>>> A().get_pk()
... A#<value_of_apple>#RedFruit

Sort Keys work in a similar fashion, except that there is no suffix.

Temporarily using a different table

There are some use-cases for using a different table (e.g. a mock table in tests for example, which I do in this repository), you can use the context manager to do so:

def ...():
  ...
  TABLE_NAME = "another table"
  dynamodb = boto3.client("dynamodb", region_name="us-east-1")
  dynamodb.create_table(**TABLE_DEFINITION)
  waiter = dynamodb.get_waiter("table_exists")
  waiter.wait(TableName=TABLE_NAME)
  with connection.table.table_context(TABLE_NAME, client=dynamodb):
    yield dynamodb
  ...