Skip to content

Commit 4559879

Browse files
committed
Added first lab notebook
1 parent ae35706 commit 4559879

File tree

1 file changed

+315
-0
lines changed

1 file changed

+315
-0
lines changed

Labs/lab_1_first_application.ipynb

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# First Cosmos DB for MongoDB API application"
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": null,
13+
"metadata": {},
14+
"outputs": [],
15+
"source": [
16+
"import os\n",
17+
"import pymongo\n",
18+
"from pprint import pprint\n",
19+
"from dotenv import load_dotenv\n",
20+
"from models import Product"
21+
]
22+
},
23+
{
24+
"cell_type": "markdown",
25+
"metadata": {},
26+
"source": [
27+
"## Create a database\n",
28+
"\n",
29+
"In creating a database connection to the MongoDB API, it will create a new database if it does not already exist. In this case, ensure the database connection string is located in a `.env` file in the root of the project, you will need to create this file. The `.env` file should contain the following value (replace the value with your own connection string):\n",
30+
"\n",
31+
"DB_CONNECTION_STRING=\"mongodb__connection_string\"\n",
32+
"\n",
33+
">**Note**: If you are running using the **local emulator**, append the following value to the connection string: `&retrywrites=false&tlsallowinvalidcertificates=true`. Also ensure that you are starting the emulator using the [MongoDB endpoint option](https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-develop-emulator?tabs=windows%2Cpython&pivots=api-mongodb#start-the-emulator).\n"
34+
]
35+
},
36+
{
37+
"cell_type": "code",
38+
"execution_count": null,
39+
"metadata": {},
40+
"outputs": [],
41+
"source": [
42+
"load_dotenv()\n",
43+
"CONNECTION_STRING = os.environ.get(\"DB_CONNECTION_STRING\")\n",
44+
"client = pymongo.MongoClient(CONNECTION_STRING)\n",
45+
"# Create database to hold cosmic works data\n",
46+
"# MongoDB will create the database if it does not exist\n",
47+
"db = client.cosmic_works"
48+
]
49+
},
50+
{
51+
"cell_type": "markdown",
52+
"metadata": {},
53+
"source": [
54+
"## Create a collection\n",
55+
"\n",
56+
"Creating collections behaves similarly to the database creation. If the collection does not exist, it will be created. It's important to note that databases and collections are lazily created. This means that the database and collection will not be created until the first document is inserted."
57+
]
58+
},
59+
{
60+
"cell_type": "code",
61+
"execution_count": null,
62+
"metadata": {},
63+
"outputs": [],
64+
"source": [
65+
"collection = db.products"
66+
]
67+
},
68+
{
69+
"cell_type": "markdown",
70+
"metadata": {},
71+
"source": [
72+
"## Create a document\n",
73+
"\n",
74+
"Documents in Cosmos DB API for MongoDB are represented as JSON objects. In this lab, the Pydantic library is used to create a model for the document. This model is then used to create a document in the database using built-in serialization methods. Find the models in the `models` folder. Notice the class property definitions include aliases, these aliases can be used to override the serialized property names. This is useful when the property names in the model do not match the property names desired in the database.\n",
75+
"\n",
76+
"One method of creating a document is using the `insert_one` method. This method takes a single document and inserts it into the database. This operation returns an [InsertOneResult](https://pymongo.readthedocs.io/en/stable/api/pymongo/results.html#pymongo.results.InsertOneResult) object that contains the property `inserted_id`. This property contains the unique identifier of the document that was just inserted."
77+
]
78+
},
79+
{
80+
"cell_type": "code",
81+
"execution_count": null,
82+
"metadata": {},
83+
"outputs": [],
84+
"source": [
85+
"product = Product(\n",
86+
" id=\"2BA4A26C-A8DB-4645-BEB9-F7D42F50262E\", \n",
87+
" category_id=\"56400CF3-446D-4C3F-B9B2-68286DA3BB99\", \n",
88+
" category_name=\"Bikes, Mountain Bikes\", \n",
89+
" sku=\"BK-M18S-42\",\n",
90+
" name=\"Mountain-100 Silver, 42\",\n",
91+
" description='The product called \"Mountain-500 Silver, 42\"',\n",
92+
" price=742.42,\n",
93+
" )\n",
94+
"\n",
95+
"# Generate JSON using alias names defined on the model\n",
96+
"product_json = product.model_dump(by_alias=True)\n",
97+
"\n",
98+
"# Insert the JSON into the database, and retrieve the inserted/generated ID\n",
99+
"product_id = collection.insert_one(product_json).inserted_id\n",
100+
"\n",
101+
"print(f\"Inserted product with ID: {product_id}\")"
102+
]
103+
},
104+
{
105+
"cell_type": "markdown",
106+
"metadata": {},
107+
"source": [
108+
"## Read a document\n",
109+
"\n",
110+
"The insertion of the Product in the previous cell automatically created the database and collection. The `find_one` method is used to retrieve a single document from the database. The `find_one` method takes a filter as an argument. This filter is used to find the document in the database. In this case, the filter is the unique identifier or `_id` of the document that was just inserted."
111+
]
112+
},
113+
{
114+
"cell_type": "code",
115+
"execution_count": null,
116+
"metadata": {},
117+
"outputs": [],
118+
"source": [
119+
"retrieved_document = collection.find_one({\"_id\": product_id})\n",
120+
"\n",
121+
"# Print the retrieved JSON document\n",
122+
"print(\"JSON document retrieved from the database:\")\n",
123+
"pprint(retrieved_document)\n",
124+
"\n",
125+
"# Cast JSON document into the Product model\n",
126+
"retrieved_product = Product(**retrieved_document)\n",
127+
"\n",
128+
"# Print the retrieved product\n",
129+
"print(\"\\nCast Product from document:\")\n",
130+
"print(retrieved_product)"
131+
]
132+
},
133+
{
134+
"cell_type": "markdown",
135+
"metadata": {},
136+
"source": [
137+
"## Update a document\n",
138+
"\n",
139+
"The `find_one_and_update` method is used to update a single document in the database. This method takes a filter and an update as arguments. The filter is used to find the document to update. The update is a dictionary of the properties to update. In this case, the `find_one_and_update` method is used to update the `name` property of the document. The updated document is the return value for this method.\n",
140+
"\n",
141+
"Find additional examples of queries in the [documentation](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/tutorial-query)."
142+
]
143+
},
144+
{
145+
"cell_type": "code",
146+
"execution_count": null,
147+
"metadata": {},
148+
"outputs": [],
149+
"source": [
150+
"retrieved_product.name = \"Mountain-100 Silver, 48\\\"\"\n",
151+
"update_result = collection.find_one_and_update(\n",
152+
" {\"_id\": product_id},\n",
153+
" {\"$set\": {\"name\": retrieved_product.name}},\n",
154+
" return_document=pymongo.ReturnDocument.AFTER\n",
155+
")\n",
156+
"print(\"Updated JSON document:\")\n",
157+
"print(update_result)\n",
158+
"updated_product = Product(**update_result)\n",
159+
"print(f\"\\nUpdated Product name: {updated_product.name}\")"
160+
]
161+
},
162+
{
163+
"cell_type": "markdown",
164+
"metadata": {},
165+
"source": [
166+
"## Delete a document\n",
167+
"\n",
168+
"The `delete_one` method is used to delete a single document from the database. This method takes a filter as an argument. This filter is used to find the document to delete. In this case, the filter is the unique identifier or `_id` of the document that was just inserted and updated."
169+
]
170+
},
171+
{
172+
"cell_type": "code",
173+
"execution_count": null,
174+
"metadata": {},
175+
"outputs": [],
176+
"source": [
177+
"delete_result = collection.delete_one({\"_id\": product_id})\n",
178+
"print(f\"Deleted documents count: {delete_result.deleted_count}\")\n",
179+
"print(f\"Number of documents in the collection: {collection.count_documents({})}\")"
180+
]
181+
},
182+
{
183+
"cell_type": "markdown",
184+
"metadata": {},
185+
"source": [
186+
"## Query for multiple documents\n",
187+
"\n",
188+
"The `find` method is used to query for multiple documents in the database. This method takes a filter as an argument. This filter is used to find the documents to return. In this case, the filter is an empty dictionary. This will return all documents in the collection."
189+
]
190+
},
191+
{
192+
"cell_type": "code",
193+
"execution_count": null,
194+
"metadata": {},
195+
"outputs": [],
196+
"source": [
197+
"# Insert multiple documents\n",
198+
"products = [\n",
199+
" Product(\n",
200+
" id=\"2BA4A26C-A8DB-4645-BEB9-F7D42F50262E\", \n",
201+
" category_id=\"56400CF3-446D-4C3F-B9B2-68286DA3BB99\", \n",
202+
" category_name=\"Bikes, Mountain Bikes\", \n",
203+
" sku=\"BK-M18S-42\",\n",
204+
" name=\"Mountain-100 Silver, 42\",\n",
205+
" description='The product called \"Mountain-500 Silver, 42\"',\n",
206+
" price=742.42\n",
207+
" ),\n",
208+
" Product(\n",
209+
" id=\"027D0B9A-F9D9-4C96-8213-C8546C4AAE71\", \n",
210+
" category_id=\"26C74104-40BC-4541-8EF5-9892F7F03D72\", \n",
211+
" category_name=\"Components, Saddles\", \n",
212+
" sku=\"SE-R581\",\n",
213+
" name=\"LL Road Seat/Saddle\",\n",
214+
" description='The product called \"LL Road Seat/Saddle\"',\n",
215+
" price=27.12\n",
216+
" ),\n",
217+
" Product(\n",
218+
" id = \"4E4B38CB-0D82-43E5-89AF-20270CD28A04\",\n",
219+
" category_id = \"75BF1ACB-168D-469C-9AA3-1FD26BB4EA4C\",\n",
220+
" category_name = \"Bikes, Touring Bikes\",\n",
221+
" sku = \"BK-T44U-60\",\n",
222+
" name = \"Touring-2000 Blue, 60\",\n",
223+
" description = 'The product called Touring-2000 Blue, 60\"',\n",
224+
" price = 1214.85\n",
225+
" ),\n",
226+
" Product(\n",
227+
" id = \"5B5E90B8-FEA2-4D6C-B728-EC586656FA6D\",\n",
228+
" category_id = \"75BF1ACB-168D-469C-9AA3-1FD26BB4EA4C\",\n",
229+
" category_name = \"Bikes, Touring Bikes\",\n",
230+
" sku = \"BK-T79Y-60\",\n",
231+
" name = \"Touring-1000 Yellow, 60\",\n",
232+
" description = 'The product called Touring-1000 Yellow, 60\"',\n",
233+
" price = 2384.07\n",
234+
" ),\n",
235+
" Product(\n",
236+
" id = \"7BAA49C9-21B5-4EEF-9F6B-BCD6DA7C2239\",\n",
237+
" category_id = \"26C74104-40BC-4541-8EF5-9892F7F03D72\",\n",
238+
" category_name = \"Components, Saddles\",\n",
239+
" sku = \"SE-R995\",\n",
240+
" name = \"HL Road Seat/Saddle\",\n",
241+
" description = 'The product called \"HL Road Seat/Saddle\"',\n",
242+
" price = 52.64,\n",
243+
" )\n",
244+
"]\n",
245+
"\n",
246+
"# The bulk_write method takes a list of write operations and executes them in the same transaction\n",
247+
"# The UpdateOne operation updates a single document, notice the upsert=True option, this means that\n",
248+
"# if the document does not exist, it will be created, if it does exist, it will be updated\n",
249+
"collection.bulk_write([pymongo.UpdateOne({\"_id\": prod.id}, {\"$set\": prod.model_dump(by_alias=True)}, upsert=True) for prod in products])"
250+
]
251+
},
252+
{
253+
"cell_type": "code",
254+
"execution_count": null,
255+
"metadata": {},
256+
"outputs": [],
257+
"source": [
258+
"# Print all documents that have a category name of \"Components, Saddles\"\n",
259+
"for result in collection.find({\"categoryName\": \"Components, Saddles\"}):\n",
260+
" pprint(result)"
261+
]
262+
},
263+
{
264+
"cell_type": "code",
265+
"execution_count": null,
266+
"metadata": {},
267+
"outputs": [],
268+
"source": [
269+
"# Print all documents that have a category name that includes the word \"Bikes\"\n",
270+
"for result in collection.find({\"categoryName\": {\"$regex\": \"Bikes\"}}):\n",
271+
" pprint(result)"
272+
]
273+
},
274+
{
275+
"cell_type": "markdown",
276+
"metadata": {},
277+
"source": [
278+
"## Clean up resources\n",
279+
"\n",
280+
"The following cell will delete the database and collection created in this lab. This is done by using the `drop_database` method on the database object. This method takes the name of the database to delete as an argument. If it is desired to simply delete the collection, the `drop_collection` method can be used on the database object. This method takes the name of the collection to delete as an argument."
281+
]
282+
},
283+
{
284+
"cell_type": "code",
285+
"execution_count": null,
286+
"metadata": {},
287+
"outputs": [],
288+
"source": [
289+
"# db.drop_collection(\"products\")\n",
290+
"client.drop_database(\"cosmic_works\")"
291+
]
292+
}
293+
],
294+
"metadata": {
295+
"kernelspec": {
296+
"display_name": ".venv",
297+
"language": "python",
298+
"name": "python3"
299+
},
300+
"language_info": {
301+
"codemirror_mode": {
302+
"name": "ipython",
303+
"version": 3
304+
},
305+
"file_extension": ".py",
306+
"mimetype": "text/x-python",
307+
"name": "python",
308+
"nbconvert_exporter": "python",
309+
"pygments_lexer": "ipython3",
310+
"version": "3.11.5"
311+
}
312+
},
313+
"nbformat": 4,
314+
"nbformat_minor": 2
315+
}

0 commit comments

Comments
 (0)