Getting Started — Accessing Oracle NoSQL Database using FastAPI and Pydantic

Dario Vega
Oracle Developers
Published in
5 min readApr 23, 2024

Let’s use the FastAPI framework in your application to manage data in Oracle NoSQL Database Cloud Service.

The sample application will show how to store, retrieve, update, query, and delete records in a NoSQL Database using borneo, the Oracle NoSQL Database Python SDK.

Do you want your Python application to access data with predictable single-digit millisecond response times at a massive scale in a highly available elastic scaling store? Do you want to be able to move your application between on-premises and the cloud at a moment’s notice? Then, let’s embark together on a 15-minute tutorial to untangle these mysteries.

Using Oracle NoSQL Database Python SDK

Understanding FastAPI

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.8+ based on standard Python type hints. While there are many micro-frameworks to build APIs using Python like Flask and Django, FastAPI has seen a huge momentum in the Dev community due to it’s performance and easy to build approach. FastAPI is inspired from other frameworks, read how it compares to other alternatives and what it learned from them.

Validate your data with Pydantic

Pydantic is the most widely used data validation library for Python. Fast and extensible, Pydantic plays nicely with your linters/IDE/brain. Define how data should be in pure, canonical Python 3.8+; validate it with Pydantic.

# Pydantic model for item data
class Image(BaseModel):
#url: str
url: HttpUrl
name: str


class Item(BaseModel):
__tablename__ = "fapi_items"
item_id: int
name: str
tags: Set[str] = set()
images: Union[List[Image], None] = None

Pydantic provides functionality to serialize model in multiple ways:

  • model_dump: Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
  • model_dump_json: Generates a JSON representation of the model using Pydantic’s to_json method.
  • parse_obj: this is very similar to the __init__ method of the model, except it takes a dict rather than keyword arguments. If the object passed is not a dict a ValidationError will be raised.

We will use those functions to convert our objects to/from dicts stored in Oracle NoSQL Database

def put(item: Item):
request = PutRequest().set_table_name(tableName)
# In this case we will use model_dump_json instead of model_dump
# because we are using Set and HttpUrl
# request.set_value(item.model_dump());
request.set_value_from_json(item.model_dump_json());
result = handle.put(request)
def get_item(item_id: int):
request = GetRequest().set_key({key: item_id}).set_table_name(tableName)
result = handle.get(request)
return (Item.parse_obj(result.get_value()))

Oracle NoSQL Database Data Model

Proper modeling of your data is crucial to application performance, extensibility, application correctness, and finally, the ability for your application to support rich user experiences.

Unlike the relational database world with purely fixed schemas, NoSQL Database is largely about schema flexibility — that is the ability to easily change how data is organized and stored.

Oracle NoSQL Database 23.3+ supports JSON Collection tables. This is particularly useful for applications that store and retrieve their data purely as documents. JSON Collection tables are created to simplify the management and manipulation of documents. The JSON collection table eliminates the need to declare fields as type JSON during table creation. When you insert data into the table, each row is inserted as a single document containing any number of JSON fields.

CREATE TABLE if NOT EXISTS fapi_items(
item_id LONG, PRMIARY KEY(item_id)
) AS JSON COLLECTION

And we are already using pydantic to validate the data in our application.

SQL for Oracle NoSQL Database

Welcome to SQL for Oracle NoSQL Database. This query language provides statetements that can be used from the Oracle NoSQL Database SDKs. The SQL for Oracle NoSQL Database data model supports flat relational data, hierarchical typed (schema-full) data, and schema-less JSON data. SQL for Oracle NoSQL Database is designed to handle all such data in a seamless fashion without any “impedance mismatch” among the different sub models.

def get_items(page: int = 0, limit: int = 10, orderby: str = "item_id", where: str = "" ):
statement = ("SELECT * FROM {table} {where} ORDER BY {orderby} LIMIT {limit} OFFSET {offset}").format(table=tableName,where=where,orderby=orderby,limit=limit,offset=limit*page)
request = QueryRequest().set_statement(statement)
qiresult = handle.query_iterable(request)
items = list()
for row in qiresult:
items.append(Item.parse_obj(row))
return items

You need 15 minutes and

Step1. Start a container image using Oracle NoSQL Database KVLite CE 23.3

docker pull ghcr.io/oracle/nosql:latest-ce
docker tag ghcr.io/oracle/nosql:latest-ce oracle/nosql:ce
docker run -d --name=kvlite --hostname=kvlite --env KV_PROXY_PORT=8080 \
-p 8080:8080 oracle/nosql:ce

Step 2. Clone the Github oracle/nosql-examples repository or just retrieve the fastapi-oracle-nosql-example.zip file

# Clone the Github repository
# git clone https://github.com/oracle/nosql-examples.git
# cd nosql-examples

# Use the fastapi-oracle-nosql-example.zip file from the GitHub Repository
curl -L https://github.com/oracle/nosql-examples/raw/master/zips/fastapi-oracle-nosql-example.zip -o fastapi-oracle-nosql-example.zip
unzip fastapi-oracle-nosql-example.zip
rm -f fastapi-oracle-nosql-example.zip

cd examples-nosql-python-sdk/fastapi-oracle-nosql-example

Step 3. Install the required packages using pip

$ python3 -V
Python 3.8.14

$ cat requirements.txt
fastapi[all]
oci
borneo
uvicorn
pydantic

$ python3 -m pip install -r requirements.txt

Step 4. Review the FastAPI app code

$ cat myfapi.py

Step 5. Running the FastAPI App

$ uvicorn myfapi:app --host 0.0.0.0 --port 8000 --reload

Step 6. Test the API Endpoints

To use the FastAPI app, you can use the ‘Try it out’ buttons on http://localhost:8000/docs or alternatively use a command line tool such as curl.

  • POST: to create data
curl -X 'POST' \
'http://localhost:8000/items/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"item_id":1,
"name": "Foo",
"tags": [
"rock",
"metal",
"metal",
"bar"
],
"images": [
{
"url": "http://example.com/baz.jpg",
"name": "The Foo live"
},
{
"url": "http://example.com/dave.jpg",
"name": "The Baz"
}
]
}'
  • GET: to read data
curl -X 'GET' \
'http://localhost:8000/items/1' \
-H 'accept: application/json'
curl -X 'GET' \
'http://localhost:8000/items/?page=0&limit=10' \
-H 'accept: application/json'
  • PUT: to update data
curl -X 'PUT' \
'http://localhost:8000/items/1' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"item_id":1,
"name": "Foo",
"tags": [
"rock",
"metal",
"bar"
],
"images": [
{
"url": "http://example.com/baz23.jpg",
"name": "The Foo live"
},
{
"url": "http://example.com/dave23.jpg",
"name": "The Baz"
}
]
}'
  • DELETE: to delete data
curl -X 'DELETE' \
'http://localhost:8000/items/1'

Oracle Developers and Oracle OCI Free Tier

Join our Oracle Developers channel on Slack to discuss this and other topics!

Build, test, and deploy your applications on Oracle Cloud — for free! Get access to OCI Cloud Free Tier!

--

--

Dario Vega
Oracle Developers

Product Manager ☁️ noSQL | inMemory | OCI | cloud-native | serverless | Architecture | Development | Open Source | DevRel