├── .gitignore ├── .devcontainer └── devcontainer.json ├── assets └── dataexplorer.png ├── LICENSE ├── family.py ├── README.md └── cosmos_get_started.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "python:3.9" 3 | } 4 | -------------------------------------------------------------------------------- /assets/dataexplorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/azure-cosmos-db-python-getting-started/HEAD/assets/dataexplorer.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /family.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | 3 | 4 | def get_andersen_family_item(): 5 | andersen_item = { 6 | 'id': 'Andersen_' + str(uuid.uuid4()), 7 | 'lastName': 'Andersen', 8 | 'district': 'WA5', 9 | 'parents': [ 10 | { 11 | 'familyName': None, 12 | 'firstName': 'Thomas' 13 | }, 14 | { 15 | 'familyName': None, 16 | 'firstName': 'Mary Kay' 17 | } 18 | ], 19 | 'children': None, 20 | 'address': { 21 | 'state': 'WA', 22 | 'county': 'King', 23 | 'city': 'Seattle' 24 | }, 25 | 'registered': True 26 | } 27 | return andersen_item 28 | 29 | def get_wakefield_family_item(): 30 | wakefield_item = { 31 | 'id': 'Wakefield_' + str(uuid.uuid4()), 32 | 'lastName': 'Wakefield', 33 | 'district': 'NY23', 34 | 'parents': [ 35 | { 36 | 'familyName': 'Wakefield', 37 | 'firstName': 'Robin' 38 | }, 39 | { 40 | 'familyName': 'Miller', 41 | 'firstName': 'Ben' 42 | } 43 | ], 44 | 'children': [ 45 | { 46 | 'familyName': 'Merriam', 47 | 'firstName': 'Jesse', 48 | 'gender': None, 49 | 'grade': 8, 50 | 'pets': [ 51 | { 52 | 'givenName': 'Goofy' 53 | }, 54 | { 55 | 'givenName': 'Shadow' 56 | } 57 | ] 58 | }, 59 | { 60 | 'familyName': 'Miller', 61 | 'firstName': 'Lisa', 62 | 'gender': 'female', 63 | 'grade': 1, 64 | 'pets': None 65 | } 66 | ], 67 | 'address': { 68 | 'state': 'NY', 69 | 'county': 'Manhattan', 70 | 'city': 'NY' 71 | }, 72 | 'registered': True 73 | } 74 | return wakefield_item 75 | 76 | def get_smith_family_item(): 77 | smith_item = { 78 | 'id': 'Johnson_' + str(uuid.uuid4()), 79 | 'lastName': 'Johnson', 80 | 'district': None, 81 | 'registered': False 82 | } 83 | return smith_item 84 | 85 | def get_johnson_family_item(): 86 | johnson_item = { 87 | 'id': 'Smith_' + str(uuid.uuid4()), 88 | 'lastName': 'Smith', 89 | 'parents': None, 90 | 'children': None, 91 | 'address': { 92 | 'state': 'WA', 93 | 'city': 'Redmond' 94 | }, 95 | 'registered': True 96 | } 97 | return johnson_item 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | languages: 4 | - python 5 | products: 6 | - azure 7 | - azure-cosmos-db 8 | description: "How to use the Azure Cosmos DB with the NoSQL API to store and access data from a Python application." 9 | urlFragment: azure-cosmos-db-python-getting-started 10 | --- 11 | 12 | # Developing a Python app using Azure Cosmos DB 13 | 14 | Azure Cosmos DB is Microsoft’s globally distributed multi-model database service. One of the supported APIs is the NoSQL API, which provides a JSON document model with SQL querying and JavaScript procedural logic. This sample shows you how to use the Azure Cosmos DB with the NoSQL API to store and access data from a Python application. 15 | 16 | > You will find a detailed Quickstart here: [Build a Python application using an Azure Cosmos DB NoSQL API account](https://docs.microsoft.com/azure/cosmos-db/create-sql-api-python) 17 | 18 | ## Running this sample 19 | 20 | * Before you can run this sample, you must have the following prerequisites: 21 | * [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest) or [Azure Cloud Shell](https://shell.azure.com) - Install if you want to execute commands via the CLI instead of the Azure portal. 22 | * [Azure Cosmos DB Account](https://docs.microsoft.com/azure/cosmos-db/) using the Azure portal or the Azure CLI. 23 | * Create with [Azure portal](https://portal.azure.com) and select 'NoSQL API'. 24 | * Create with [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest) with this command: `az cosmosdb create --name --resource-group `. Note that the default API is NoSQL when creating a Cosmos DB account with the CLI. 25 | * [Visual Studio Code](https://code.visualstudio.com/) 26 | * [Python extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-python.python#overview) 27 | * [Python 3.6+](https://www.python.org/downloads/) with \\Python36 and \\Python36\Scripts added to your PATH. 28 | * [Azure Cosmos DB Python SDK](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/cosmos/azure-cosmos) - Install with this command: `pip install azure-cosmos` 29 | 30 | * Clone this repository using: 31 | `git clone https://github.com/Azure-Samples/azure-cosmos-db-python-getting-started.git` 32 | 33 | * Open `cosmos_get_started.py` and substitute the `endpoint` (URI) and primary master `key` values with your Cosmos DB account's values from the Azure portal or via the Azure CLI with the following commands: 34 | * Endpoint: `az cosmosdb show --name --resource-group ` 35 | * Key: `az cosmosdb keys list --name --resource-group ` 36 | 37 | * In Visual Studio Code, select **View** > **Integrated terminal** to open the Visual Studio Code integrated terminal. 38 | 39 | * In the terminal, run `python cosmos_get_started.py`, which will output the following text: 40 | 41 | ```Read item with id Andersen_38c64955-fce7-4ae8-8d52-b51979f0952b. Operation consumed 1 request units 42 | Read item with id Smith_d457f895-3756-49cd-a629-e7708d7ed252. Operation consumed 1 request units 43 | Read item with id Johnson_3bd2aa16-742f-4aed-9a95-3adc548a94e3. Operation consumed 1 request units 44 | Read item with id Wakefield_c73aa98d-7104-4b01-a3da-4946081575ff. Operation consumed 1 request units 45 | Query returned 2 items. Operation consumed 3.09 request units 46 | ``` 47 | 48 | * You can view the items that this sample created by navigating to the [Azure Cosmos DB Data Explorer](https://cosmos.azure.com/) and selecting the AzureSampleFamilyDatabase: 49 | 50 | !['Azure Cosmos DB Data Explorer](assets/dataexplorer.png) 51 | 52 | ## About the code 53 | The code included in this sample is intended to get you quickly started with a Python application that connects to Azure Cosmos DB with the NoSQL API. 54 | 55 | ## More information 56 | - [Quickstart: Build a Python application using an Azure Cosmos DB NoSQL API account](https://docs.microsoft.com/azure/cosmos-db/create-sql-api-python) 57 | - [Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/introduction) 58 | - [Azure Cosmos DB: NoSQL API introduction](https://docs.microsoft.com/azure/cosmos-db/sql-api-introduction) 59 | - [Azure Cosmos DB Python SDK Reference](https://docs.microsoft.com/azure/cosmos-db/sql-api-sdk-python) 60 | -------------------------------------------------------------------------------- /cosmos_get_started.py: -------------------------------------------------------------------------------- 1 | from azure.cosmos.aio import CosmosClient as cosmos_client 2 | from azure.cosmos import PartitionKey, exceptions 3 | import asyncio 4 | import family 5 | 6 | # 7 | endpoint = "" 8 | key = "" 9 | # 10 | 11 | 12 | # 13 | database_name = 'AzureSampleFamilyDatabase' 14 | container_name = 'FamilyContainer' 15 | # 16 | 17 | # 18 | async def get_or_create_db(client, database_name): 19 | try: 20 | database_obj = client.get_database_client(database_name) 21 | await database_obj.read() 22 | return database_obj 23 | except exceptions.CosmosResourceNotFoundError: 24 | print("Creating database") 25 | return await client.create_database(database_name) 26 | # 27 | 28 | # Create a container 29 | # Using a good partition key improves the performance of database operations. 30 | # 31 | async def get_or_create_container(database_obj, container_name): 32 | try: 33 | todo_items_container = database_obj.get_container_client(container_name) 34 | await todo_items_container.read() 35 | return todo_items_container 36 | except exceptions.CosmosResourceNotFoundError: 37 | print("Creating container with lastName as partition key") 38 | return await database_obj.create_container( 39 | id=container_name, 40 | partition_key=PartitionKey(path="/lastName"), 41 | offer_throughput=400) 42 | except exceptions.CosmosHttpResponseError: 43 | raise 44 | # 45 | 46 | # 47 | async def populate_container_items(container_obj, items_to_create): 48 | # Add items to the container 49 | family_items_to_create = items_to_create 50 | # 51 | for family_item in family_items_to_create: 52 | inserted_item = await container_obj.create_item(body=family_item) 53 | print("Inserted item for %s family. Item Id: %s" %(inserted_item['lastName'], inserted_item['id'])) 54 | # 55 | # 56 | 57 | 58 | # 59 | async def read_items(container_obj, items_to_read): 60 | # Read items (key value lookups by partition key and id, aka point reads) 61 | # 62 | for family in items_to_read: 63 | item_response = await container_obj.read_item(item=family['id'], partition_key=family['lastName']) 64 | request_charge = container_obj.client_connection.last_response_headers['x-ms-request-charge'] 65 | print('Read item with id {0}. Operation consumed {1} request units'.format(item_response['id'], (request_charge))) 66 | # 67 | # 68 | 69 | # 70 | async def query_items(container_obj, query_text): 71 | # enable_cross_partition_query should be set to True as the container is partitioned 72 | # In this case, we do have to await the asynchronous iterator object since logic 73 | # within the query_items() method makes network calls to verify the partition key 74 | # definition in the container 75 | # 76 | query_items_response = container_obj.query_items( 77 | query=query_text, 78 | enable_cross_partition_query=True 79 | ) 80 | request_charge = container_obj.client_connection.last_response_headers['x-ms-request-charge'] 81 | items = [item async for item in query_items_response] 82 | print('Query returned {0} items. Operation consumed {1} request units'.format(len(items), request_charge)) 83 | # 84 | # 85 | 86 | # 87 | async def run_sample(): 88 | # 89 | async with cosmos_client(endpoint, credential = key) as client: 90 | # 91 | try: 92 | # create a database 93 | database_obj = await get_or_create_db(client, database_name) 94 | # create a container 95 | container_obj = await get_or_create_container(database_obj, container_name) 96 | # generate some family items to test create, read, delete operations 97 | family_items_to_create = [family.get_andersen_family_item(), family.get_johnson_family_item(), family.get_smith_family_item(), family.get_wakefield_family_item()] 98 | # populate the family items in container 99 | await populate_container_items(container_obj, family_items_to_create) 100 | # read the just populated items using their id and partition key 101 | await read_items(container_obj, family_items_to_create) 102 | # Query these items using the SQL query syntax. 103 | # Specifying the partition key value in the query allows Cosmos DB to retrieve data only from the relevant partitions, which improves performance 104 | query = "SELECT * FROM c WHERE c.lastName IN ('Wakefield', 'Andersen')" 105 | await query_items(container_obj, query) 106 | except exceptions.CosmosHttpResponseError as e: 107 | print('\nrun_sample has caught an error. {0}'.format(e.message)) 108 | finally: 109 | print("\nQuickstart complete") 110 | # 111 | 112 | # 113 | if __name__=="__main__": 114 | loop = asyncio.get_event_loop() 115 | loop.run_until_complete(run_sample()) 116 | # 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | --------------------------------------------------------------------------------