Skip to content

Commit d9bac58

Browse files
authored
Adding fastapi-oracle-nosql-example to examples-nosql-python-sdk (#167)
* New Example fastapi-oracle-nosql-example * Create fastapi-oracle-nosql-example.zip
1 parent 05b3d83 commit d9bac58

File tree

5 files changed

+303
-0
lines changed

5 files changed

+303
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#------------------------------------------------------------------------------
2+
# Copyright (c) 2024, Oracle and/or its affiliates.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#------------------------------------------------------------------------------
16+
17+
import os
18+
import logging
19+
20+
from borneo import (Regions, NoSQLHandle, NoSQLHandleConfig,
21+
PutRequest,QueryRequest, DeleteRequest, TableRequest, GetRequest, PutOption,QueryIterableResult,
22+
TableLimits, State,TimeToLive)
23+
from borneo.iam import SignatureProvider
24+
from borneo.kv import StoreAccessTokenProvider
25+
26+
27+
from fastapi import FastAPI, HTTPException
28+
from pydantic import BaseModel
29+
import uvicorn
30+
31+
# Pydantic model for order data
32+
class Order(BaseModel):
33+
order_id: int
34+
product_name: str
35+
quantity: int
36+
37+
38+
def get_connection():
39+
print("Connecting to the Oracle NoSQL database")
40+
provider = StoreAccessTokenProvider()
41+
config = NoSQLHandleConfig( 'http://localhost:8080', provider).set_logger(None)
42+
return(NoSQLHandle(config))
43+
44+
def create_table ():
45+
statement = 'create table if not exists fapi_orders(order_id LONG, primary key(order_id)) AS JSON COLLECTION'
46+
request = TableRequest().set_statement(statement)
47+
result = handle.do_table_request(request, 40000, 3000)
48+
result = handle.table_request(request)
49+
result.wait_for_completion(handle, 40000, 3000)
50+
print (statement)
51+
52+
# Create a connection pool
53+
handle = get_connection()
54+
# Set up the schema
55+
create_table()
56+
# Define the FastAPI app
57+
app = FastAPI()
58+
59+
# Endpoint to create an order
60+
@app.post("/orders/", response_model=Order)
61+
def create_order(order: Order):
62+
request = PutRequest().set_table_name("fapi_orders").set_option(PutOption.IF_ABSENT)
63+
request.set_value(order.model_dump());
64+
result = handle.put(request)
65+
if result.get_version() is not None:
66+
return order
67+
else:
68+
raise HTTPException(status_code=404, detail="Error Insterting - Order found")
69+
70+
# Endpoint to retrieve orders
71+
#@app.get("/orders/",response_model=list[Order])
72+
@app.get("/orders/")
73+
def get_orders() -> Any:
74+
statement = 'select * from fapi_orders order by order_id'
75+
request = QueryRequest().set_statement(statement)
76+
qiresult = handle.query_iterable(request)
77+
orders = []
78+
for row in qiresult:
79+
orders.append(row)
80+
return orders
81+
82+
# Endpoint to retrieve an order by ID
83+
@app.get("/orders/{order_id}", response_model=Order)
84+
def get_order(order_id: int):
85+
request = GetRequest().set_key({'order_id': order_id}).set_table_name("fapi_orders")
86+
result = handle.get(request)
87+
if result.get_value() is None:
88+
raise HTTPException(status_code=404, detail="Order not found")
89+
else:
90+
return (result.get_value())
91+
92+
# Endpoint to update an order by ID
93+
@app.put("/orders/{order_id}", response_model=Order)
94+
def update_order(order_id: int, order: Order):
95+
request = PutRequest().set_table_name("fapi_orders").set_option(PutOption.IF_PRESENT)
96+
request.set_value(order.model_dump());
97+
result = handle.put(request)
98+
if result.get_version() is not None:
99+
return order
100+
else:
101+
raise HTTPException(status_code=404, detail="Error Updating - Order not found")
102+
103+
# Endpoint to delete an order by ID
104+
@app.delete("/orders/{order_id}")
105+
def delete_order(order_id: int):
106+
request = DeleteRequest().set_key({'order_id': order_id}).set_table_name("fapi_orders")
107+
result = handle.delete(request)
108+
if result.get_success():
109+
return {"message": "Order deleted successfully"}
110+
else:
111+
raise HTTPException(status_code=404, detail="Order not found")
112+
113+
# Close the connection pool on app shutdown
114+
@app.on_event("shutdown")
115+
def shutdown_event():
116+
if handle is not None:
117+
handle.close()
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#------------------------------------------------------------------------------
2+
# Copyright (c) 2024, Oracle and/or its affiliates.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#------------------------------------------------------------------------------
16+
17+
import os
18+
import logging
19+
import uvicorn
20+
21+
from borneo import (NoSQLHandle, NoSQLHandleConfig ,
22+
TableLimits, State,
23+
PutRequest,QueryRequest, DeleteRequest, TableRequest, GetRequest, PutOption, QueryIterableResult )
24+
25+
from borneo.kv import StoreAccessTokenProvider
26+
#from borneo.iam import SignatureProvider
27+
28+
29+
from typing import List, Set, Union, Any
30+
from pydantic import BaseModel, HttpUrl
31+
from fastapi import FastAPI, HTTPException
32+
33+
# Pydantic model for item data
34+
class Image(BaseModel):
35+
#url: str
36+
url: HttpUrl
37+
name: str
38+
39+
40+
class Item(BaseModel):
41+
__tablename__ = "fapi_items"
42+
item_id: int
43+
name: str
44+
tags: Set[str] = set()
45+
#tags: List[str] = []
46+
#tags: list = []
47+
images: Union[List[Image], None] = None
48+
49+
50+
def get_connection():
51+
# Learn more https://nosql-python-sdk.readthedocs.io/en/stable/installation.html#configuring-the-sdk
52+
print("Connecting to the Oracle NoSQL database")
53+
provider = StoreAccessTokenProvider()
54+
config = NoSQLHandleConfig( 'http://localhost:8080', provider).set_logger(None)
55+
return(NoSQLHandle(config))
56+
57+
58+
def create_table ():
59+
# Learn more https://nosql-python-sdk.readthedocs.io/en/stable/tables.html
60+
# Learn more https://docs.oracle.com/en/database/other-databases/nosql-database/23.3/nsdev/schema-flexibility-oracle-nosql-database.html
61+
statement = 'create table if not exists fapi_items(item_id LONG, primary key(item_id)) AS JSON COLLECTION'
62+
request = TableRequest().set_statement(statement).set_table_limits( TableLimits(20, 10, 5))
63+
result = handle.do_table_request(request, 40000, 3000)
64+
result = handle.table_request(request)
65+
result.wait_for_completion(handle, 40000, 3000)
66+
print (statement)
67+
68+
# Create the NoSQL handle and NoSQL the JSON COLLECTION table
69+
tableName="fapi_items"
70+
key="item_id"
71+
handle = get_connection()
72+
create_table()
73+
# Define the FastAPI app
74+
app = FastAPI()
75+
76+
77+
# Endpoint to create an item
78+
@app.post("/items/",
79+
response_model=Item,
80+
summary="Create an item",
81+
response_description="A document containing all information about a Item"
82+
)
83+
def create_item(item: Item):
84+
# Learn more https://nosql-python-sdk.readthedocs.io/en/stable/tables.html
85+
# See the option IF_ABSENT
86+
request = PutRequest().set_table_name(tableName).set_option(PutOption.IF_ABSENT)
87+
#request.set_value(item.model_dump());
88+
request.set_value_from_json(item.model_dump_json());
89+
result = handle.put(request)
90+
if result.get_version() is not None:
91+
return item
92+
else:
93+
raise HTTPException(status_code=404, detail="Error Insterting - Item found")
94+
95+
# Endpoint to retrieve items
96+
@app.get("/items/",
97+
# Validate a list[Items] needs python 3.9 or 3.10
98+
# response_model=list[Item],
99+
summary="Gets all item",
100+
response_description="A list containing all information about the Items"
101+
)
102+
def get_items(page: int = 0, limit: int = 10, orderby: str = "item_id", where: str = "" ):
103+
try:
104+
statement = ("SELECT * FROM {table} {where} ORDER BY {orderby} LIMIT {limit} OFFSET {offset}").format(table=tableName,where=where,orderby=orderby,limit=limit,offset=limit*page)
105+
print(statement)
106+
request = QueryRequest().set_statement(statement)
107+
qiresult = handle.query_iterable(request)
108+
items = list()
109+
for row in qiresult:
110+
try:
111+
items.append(Item.parse_obj(row))
112+
return items
113+
except Exception as e:
114+
print("---- Ignoring bad records")
115+
print(f"Error: {e}")
116+
continue
117+
except Exception as e:
118+
raise HTTPException(status_code=500, detail=f"Error: {e}")
119+
120+
# Endpoint to retrieve an item by ID
121+
@app.get("/items/{item_id}",
122+
response_model=Item,
123+
summary="Gets an item",
124+
response_description="A document containing all information about a Item"
125+
)
126+
def get_item(item_id: int):
127+
# Learn more https://nosql-python-sdk.readthedocs.io/en/stable/tables.html
128+
try:
129+
request = GetRequest().set_key({key: item_id}).set_table_name(tableName)
130+
result = handle.get(request)
131+
except Exception as e:
132+
raise HTTPException(status_code=500, detail=f"Error: {e}")
133+
if result.get_value() is None:
134+
raise HTTPException(status_code=404, detail="Item not found")
135+
else:
136+
try:
137+
item = Item.parse_obj(result.get_value())
138+
# return (result.get_value())
139+
return (Item.parse_obj(result.get_value()))
140+
except Exception as e:
141+
raise HTTPException(status_code=500, detail=f"Error: {e}")
142+
143+
# Endpoint to update an item by ID
144+
@app.put("/items/{item_id}",
145+
response_model=Item,
146+
summary="Update an item",
147+
response_description="A document containing all information about a Item"
148+
)
149+
def update_item(item_id: int, item: Item):
150+
# Learn more https://nosql-python-sdk.readthedocs.io/en/stable/tables.html
151+
# See the option IF_PRESENT
152+
request = PutRequest().set_table_name(tableName).set_option(PutOption.IF_PRESENT)
153+
#request.set_value(item.model_dump());
154+
request.set_value_from_json(item.model_dump_json());
155+
result = handle.put(request)
156+
if result.get_version() is not None:
157+
return item
158+
else:
159+
raise HTTPException(status_code=404, detail="Error Updating - Item not found")
160+
161+
# Endpoint to delete an item by ID
162+
@app.delete("/items/{item_id}",
163+
summary="Delete an item",
164+
response_description="A message indicating the Itemi was deleted"
165+
)
166+
def delete_item(item_id: int):
167+
# Learn more https://nosql-python-sdk.readthedocs.io/en/stable/tables.html
168+
request = DeleteRequest().set_key({key: item_id}).set_table_name(tableName)
169+
result = handle.delete(request)
170+
if result.get_success():
171+
return {"message": "Item deleted successfully"}
172+
else:
173+
raise HTTPException(status_code=404, detail="Item not found")
174+
175+
# Close the connection pool on app shutdown
176+
@app.on_event("shutdown")
177+
def shutdown_event():
178+
if handle is not None:
179+
print("Disconnecting from the Oracle NoSQL database")
180+
handle.close()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fastapi[all]
2+
oci
3+
borneo
4+
uvicorn
5+
pydantic
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Generate a zip file - it allows to retrieve the example without forking all the repository
4.97 KB
Binary file not shown.

0 commit comments

Comments
 (0)