Effectively manage the change of field data type of PynamoDB, an object-relational mapper (ORM) for DynamoDB. Ensure smooth database schema updates and maintain application performance and integrity with this guide.
PynamoDB, with a Python interface, is a great ORM for AWS DynamoDB. DynamoDB is a NoSQL database with scalability and security and it has awesome API and SDKs. PynamoDB wraps the underneath APIs of DynamoDB and gives a beautiful pythonic way to use DynamoDB.
In real-world our DB fields are not constant. It can change with the requirements update of our project. The hard part is when you have to maintain the old and new features. For example, a field data type can change from String to Binary. So if any API e.g. REST API with versioning is working with DynamoDB, you have to accept both old data type (String) and new data type (Binary). We are going to find a solution in such a case.
Let’s start with setting a goal. Assume we have a field with Dynamo data type List. But after times it changes to Map. So we will do
Let’s add a couple of files to do our task.
# Add project folder mkdir change-field-ddb cd change-field-ddb # Add Pipfile for requirements mange with pipenv touch Pipfile # For Custom PynamoDB attributes touch attributes.py # Add models.py to add pynamo model touch models.py # To test everything touch test.py
Add following requirements to Pipfile
[dev-packages] pipenv = "==2020.8.13" moto = "==1.3.14" [packages] pynamodb = "==4.3.2" [requires] python_version = "3.8"
Now initiate pipenv with
pipenv install
Now the project will look like
tree . ├── attributes.py ├── models.py ├── Pipfile ├── Pipfile.lock └── test.py
Let’s assume our previous datatype (List) for a field result is
[3.75, 3.17, 3.90, 3.67, .......]
So the result stores CGPA of a student from 1st semester to final semester e.g. result[0] as 1st semester, result[1] as 2nd semester, and so on. But we will make it better (Map) at the updated version
{
'semester 1': 3.75,
'semester 2': 3.17,
'semester 3': 3.90,
'semester 4': 3.67,
..................
}
Add the custom PynamoDB attribute to accept old (List) and new (Map) attribute and saves only as Map. But at return time it will return old (List) data as Map and also new data as Map. Also, we are going to use custom UUIDAttribute which will be used as a hash key.
We are going to start with a simple PynamoDB Model only with 2 fields
Add some tests in test.py
Run tests with
pipenv shell python3 test.py
Full code can be found here:
https://github.com/melon-ruet/change-field-ddb