1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Python を使用して Azure CosmosDB に接続して 自動生成データを書き込みしてみました

Posted at

概要

この記事 の CosmosDB版です。 指定した件数・間隔でデータを自動生成し、CosmosDBのデータベースに書き込む Python プログラムです。データの読み込み・削除も可能となっています。

ローカル環境

macOS Monterey 12.3.1
python 3.8.12
Azure CLI 2.34.1

前提条件

  1. Azure環境がすでに用意されていること(テナント/サブスクリプション)
  2. ローカル環境に「azure cli」がインストールされていること

事前準備

この記事 を実行し、Azure CosmosDB を プロビジョニングされたスループット構成 で作成できていること

項目
Endpoint https://iturucosmosdb01.documents.azure.com:443/
CosmosDB アカウント名 iturucosmosdb01
データベース名 CPDemoDB01
コンテナ名 container01
パーティション section

Pythonプログラムからの CosmosDB への操作

Pythonプログラム

cosmosdb_IoTdummy.py
import time
from datetime import date, datetime
import random
import json
import argparse
import string
from faker.factory import Factory
import pandas as pd
from azure.cosmos import exceptions, CosmosClient, PartitionKey

endpoint = 'https://iturucosmosdb01.documents.azure.com:443/'
key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
databaseName = 'CPDemoDB01'
containerName = 'container01'


# ダミーデータ作成のための Faker の使用
Faker = Factory.create
fake = Faker()
fake = Faker("ja_JP")

# ダミーセクション?(大文字アルファベットを定義)
section = string.ascii_uppercase


# JSONダミーデータの作成
def iot_json_data(count, proc):
    iot_items = json.dumps({
        'items': [{
            'id': str(datetime.now().timestamp()),  # id
            'ctid': i,                              # create id
            'proc': proc,                           # データ生成プロセス名
            'section': random.choice(section),      # IoT機器セクション
            'iot_num': fake.zipcode(),              # IoT機器番号
            'iot_state': fake.prefecture(),         # IoT設置場所
            'val_1': random.uniform(100, 200),      # IoT値−1
            'val_2': random.uniform(50, 90),        # IoT値−2
            'created_at': generate_time()           # データ生成時間
            } 
            for i in range(count)
        ]
    }, ensure_ascii=False).encode('utf-8')
    return iot_items


# IoT機器で計測されたダミーデータの生成時間
def generate_time():
    dt_time = datetime.now()
    gtime = json_trans_date(dt_time)
    return gtime

# date, datetimeの変換関数
def json_trans_date(obj):
    # 日付型を文字列に変換
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    # 上記以外は対象外.
    raise TypeError ("Type %s not serializable" % type(obj))


# CosmosDBへの接続
def ConnectionToCosmosDB():
    try:
      client = CosmosClient(endpoint, key)
      db = client.get_database_client(databaseName)
      container = db.get_container_client(containerName)
      return 1, container
    except Exception as err:
      return 0, err


# メイン : ターミナル出力用
def tm_main(count, proc, wait):
    print('ターミナル 出力\n')

    # ダミーデータ生成
    iotjsondata = iot_json_data(count, proc)
    json_dict = json.loads(iotjsondata)

    # ターミナル出力
    for item in json_dict['items']:
        print(item)
        time.sleep(wait)


# メイン : Show Database
def show_db_main():
    print('CosmosDB への接続確認')
    code, conn = ConnectionToCosmosDB()

    if code == 0 :
      print(conn)
    else :
      print(conn)


# メイン : Write Database
def write_db_main(count, proc, wait):
    print('データベースへのデータ書き込み')

    # DBへの接続
    code, conn = ConnectionToCosmosDB()

    if code == 0 :
      print(conn)
      return

    # ダミーデータ生成
    iotjsondata = iot_json_data(count, proc)
    json_dict = json.loads(iotjsondata)

    # データの書き込み
    try:
      for item in json_dict['items']:
        print(list(item.values()))
        conn.create_item(item)
        time.sleep(wait)
      print("\nInserted",count,"row(s) of data.")
      print("Done.")
    except Exception as err:
      print(err)


# メイン : Read Database
def read_db_main():
    print('データベースからのデータ読み込み')

    # DBへの接続
    code, conn = ConnectionToCosmosDB()

    if code == 0 :
      print(conn)
      return

    # Read table data
    items = conn.read_all_items()

    # print all rows
    try:
      [print(f'{item}') for item in items]
      print("Done.")
    except Exception as err:
      print(err)


# メイン : Delete Database
def delete_db_main():
    print('データベースのデータ全削除')

    # DBへの接続
    code, conn = ConnectionToCosmosDB()

    if code == 0 :
      print(conn)
      return

    try:
      for item in conn.query_items(query='SELECT * FROM container01',enable_cross_partition_query=True):
          print(item['section'])
          conn.delete_item(item, partition_key=item['section'])
      print("Done.")
    except Exception as err:
      print(err)


# メイン
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='ダミーデータの自動生成からのDBへの書込み')
    parser.add_argument('--count', type=int, default=5, help='データ作成件数(デフォルト:5件)')
    parser.add_argument('--proc', type=str, default='111', help='データ作成プロセス名(デフォルト:111)')
    parser.add_argument('--mode', type=str, default='tm', help='tm(Terminal(デフォルト))/ db(db操作)')
    parser.add_argument('--wait', type=float, default=1, help='データ生成間隔(デフォルト:1.0秒)')
    parser.add_argument('--db', type=str, default='show', help='show(デフォルト) / write / read / delete')
    args = parser.parse_args()

    start = time.time()

    if (args.mode == 'tm'): 
      tm_main(args.count, args.proc, args.wait)
    elif (args.mode == 'db'):
      if (args.db == 'show'):
        show_db_main()
      elif (args.db == 'write'):
        write_db_main(args.count, args.proc, args.wait)
      elif (args.db == 'read'):
        read_db_main()
      elif (args.db == 'delete'):
        delete_db_main()
    else :
      print("パラメータ設定を確認ください --help")

    making_time = time.time() - start

    print("")
    print("処理時間:{0}".format(making_time) + " [sec]")
    print("")

プログラムの実行

  • 実行パラメータを指定することにより以下の処理が可能となります
    • データ生成
      • パラメータ
        • --mode
          • tm : 生成データのターミナル出力(デフォルト)
          • db : DB操作の実施
        • --proc : 本プログラム実行場所の識別子(デフォルト:'111')
        • --count : 生成データの件数(デフォルト:5件)
        • --wait : データ書込み時の間隔(秒)(デフォルト:1.0秒、最小:0秒)
    • DB操作
      • パラメータ(上記「mode」パラメータで「db」を選択することにより有効となります)
        • --db
          • show : データベースへの接続確認(デフォルト)
          • write : テーブルへの生成データ書き込み
          • read : テーブルからの全件データ読み込み
          • delete : テーブルの全件データ削除

ヘルプ表示

$ python cosmosdb_IoTdummy.py -h                  
usage: cosmosdb_IoTdummy.py [-h] [--count COUNT] [--proc PROC] [--mode MODE] [--wait WAIT] [--db DB]

ダミーデータの自動生成からのDBへの書込み

optional arguments:
  -h, --help     show this help message and exit
  --count COUNT  データ作成件数(デフォルト:5件)
  --proc PROC    データ作成プロセス名(デフォルト:111)
  --mode MODE    tm(Terminal(デフォルト))/ db(db操作)
  --wait WAIT    データ生成間隔(デフォルト:1.0秒)
  --db DB        show(デフォルト) / write / read / delete

ターミナルへの生成データの出力

$ python cosmosdb_IoTdummy.py   
ターミナル 出力

{'id': '1652363331.254743', 'ctid': 0, 'proc': '111', 'section': 'N', 'iot_num': '606-9267', 'iot_state': '京都府', 'val_1': 141.51992902165148, 'val_2': 67.06060158494354, 'created_at': '2022-05-12T22:48:51.254792'}
{'id': '1652363331.254798', 'ctid': 1, 'proc': '111', 'section': 'F', 'iot_num': '963-8665', 'iot_state': '山梨県', 'val_1': 190.62681621674932, 'val_2': 52.34280626979511, 'created_at': '2022-05-12T22:48:51.254835'}
{'id': '1652363331.254838', 'ctid': 2, 'proc': '111', 'section': 'Z', 'iot_num': '131-3410', 'iot_state': '熊本県', 'val_1': 199.5290412707653, 'val_2': 61.636601101310475, 'created_at': '2022-05-12T22:48:51.254867'}
{'id': '1652363331.254869', 'ctid': 3, 'proc': '111', 'section': 'H', 'iot_num': '041-2071', 'iot_state': '山形県', 'val_1': 144.47870335349302, 'val_2': 76.18492745985165, 'created_at': '2022-05-12T22:48:51.254881'}
{'id': '1652363331.254883', 'ctid': 4, 'proc': '111', 'section': 'H', 'iot_num': '883-0190', 'iot_state': '高知県', 'val_1': 198.43396241325718, 'val_2': 55.100609116813224, 'created_at': '2022-05-12T22:48:51.254894'}

処理時間:5.012450933456421 [sec]

DBへの接続確認

$ python cosmosdb_IoTdummy.py --mode db --db show
CosmosDB への接続確認
<ContainerProxy [dbs/CPDemoDB01/colls/container01]>

処理時間:0.23801898956298828 [sec]

データの書き込み

## 8件のデータを0.2秒間隔で書き込む
$ python cosmosdb_IoTdummy.py --mode db --db write --count 8 --wait 0.2
データベースへのデータ書き込み
['1652363480.937302', 0, '111', 'B', '640-6595', '長崎県', 124.29416912385994, 78.0063814862435, '2022-05-12T22:51:20.937444']
['1652363480.937457', 1, '111', 'O', '572-2593', '千葉県', 116.3744925587041, 76.85188192753809, '2022-05-12T22:51:20.937495']
['1652363480.937501', 2, '111', 'C', '854-2449', '石川県', 164.8104189841249, 70.86096920541297, '2022-05-12T22:51:20.937530']
['1652363480.937535', 3, '111', 'E', '326-5458', '新潟県', 177.18539247589842, 88.7860288485881, '2022-05-12T22:51:20.937578']
['1652363480.937583', 4, '111', 'T', '331-7151', '宮城県', 176.29096635579108, 58.605170597776066, '2022-05-12T22:51:20.937609']
['1652363480.937614', 5, '111', 'Q', '376-7413', '高知県', 114.1503599127303, 62.52303505813319, '2022-05-12T22:51:20.937639']
['1652363480.937644', 6, '111', 'C', '427-4899', '北海道', 185.81540242201626, 53.17876457695124, '2022-05-12T22:51:20.937669']
['1652363480.937673', 7, '111', 'K', '318-8102', '福井県', 139.14614950001638, 65.42312161402906, '2022-05-12T22:51:20.937698']

Inserted 8 row(s) of data.
Done.

処理時間:2.137359142303467 [sec]

データの全件読み込み

$ python cosmosdb_IoTdummy.py --mode db --db read                      
データベースからのデータ読み込み
{'id': '1652363480.937302', 'ctid': 0, 'proc': '111', 'section': 'B', 'iot_num': '640-6595', 'iot_state': '長崎県', 'val_1': 124.29416912385994, 'val_2': 78.0063814862435, 'created_at': '2022-05-12T22:51:20.937444', '_rid': 'PQFjAP5XJMoSAAAAAAAAAA==', '_self': 'dbs/PQFjAA==/colls/PQFjAP5XJMo=/docs/PQFjAP5XJMoSAAAAAAAAAA==/', '_etag': '"340014e3-0000-2300-0000-627d10db0000"', '_attachments': 'attachments/', '_ts': 1652363483}
{'id': '1652363480.937457', 'ctid': 1, 'proc': '111', 'section': 'O', 'iot_num': '572-2593', 'iot_state': '千葉県', 'val_1': 116.3744925587041, 'val_2': 76.85188192753809, 'created_at': '2022-05-12T22:51:20.937495', '_rid': 'PQFjAP5XJMoTAAAAAAAAAA==', '_self': 'dbs/PQFjAA==/colls/PQFjAP5XJMo=/docs/PQFjAP5XJMoTAAAAAAAAAA==/', '_etag': '"340015e3-0000-2300-0000-627d10db0000"', '_attachments': 'attachments/', '_ts': 1652363483}
{'id': '1652363480.937501', 'ctid': 2, 'proc': '111', 'section': 'C', 'iot_num': '854-2449', 'iot_state': '石川県', 'val_1': 164.8104189841249, 'val_2': 70.86096920541297, 'created_at': '2022-05-12T22:51:20.937530', '_rid': 'PQFjAP5XJMoUAAAAAAAAAA==', '_self': 'dbs/PQFjAA==/colls/PQFjAP5XJMo=/docs/PQFjAP5XJMoUAAAAAAAAAA==/', '_etag': '"340016e3-0000-2300-0000-627d10db0000"', '_attachments': 'attachments/', '_ts': 1652363483}
{'id': '1652363480.937535', 'ctid': 3, 'proc': '111', 'section': 'E', 'iot_num': '326-5458', 'iot_state': '新潟県', 'val_1': 177.18539247589842, 'val_2': 88.7860288485881, 'created_at': '2022-05-12T22:51:20.937578', '_rid': 'PQFjAP5XJMoVAAAAAAAAAA==', '_self': 'dbs/PQFjAA==/colls/PQFjAP5XJMo=/docs/PQFjAP5XJMoVAAAAAAAAAA==/', '_etag': '"340018e3-0000-2300-0000-627d10db0000"', '_attachments': 'attachments/', '_ts': 1652363483}
{'id': '1652363480.937583', 'ctid': 4, 'proc': '111', 'section': 'T', 'iot_num': '331-7151', 'iot_state': '宮城県', 'val_1': 176.29096635579108, 'val_2': 58.605170597776066, 'created_at': '2022-05-12T22:51:20.937609', '_rid': 'PQFjAP5XJMoWAAAAAAAAAA==', '_self': 'dbs/PQFjAA==/colls/PQFjAP5XJMo=/docs/PQFjAP5XJMoWAAAAAAAAAA==/', '_etag': '"34001be3-0000-2300-0000-627d10dc0000"', '_attachments': 'attachments/', '_ts': 1652363484}
{'id': '1652363480.937614', 'ctid': 5, 'proc': '111', 'section': 'Q', 'iot_num': '376-7413', 'iot_state': '高知県', 'val_1': 114.1503599127303, 'val_2': 62.52303505813319, 'created_at': '2022-05-12T22:51:20.937639', '_rid': 'PQFjAP5XJMoXAAAAAAAAAA==', '_self': 'dbs/PQFjAA==/colls/PQFjAP5XJMo=/docs/PQFjAP5XJMoXAAAAAAAAAA==/', '_etag': '"34001ce3-0000-2300-0000-627d10dc0000"', '_attachments': 'attachments/', '_ts': 1652363484}
{'id': '1652363480.937644', 'ctid': 6, 'proc': '111', 'section': 'C', 'iot_num': '427-4899', 'iot_state': '北海道', 'val_1': 185.81540242201626, 'val_2': 53.17876457695124, 'created_at': '2022-05-12T22:51:20.937669', '_rid': 'PQFjAP5XJMoYAAAAAAAAAA==', '_self': 'dbs/PQFjAA==/colls/PQFjAP5XJMo=/docs/PQFjAP5XJMoYAAAAAAAAAA==/', '_etag': '"34001de3-0000-2300-0000-627d10dc0000"', '_attachments': 'attachments/', '_ts': 1652363484}
{'id': '1652363480.937673', 'ctid': 7, 'proc': '111', 'section': 'K', 'iot_num': '318-8102', 'iot_state': '福井県', 'val_1': 139.14614950001638, 'val_2': 65.42312161402906, 'created_at': '2022-05-12T22:51:20.937698', '_rid': 'PQFjAP5XJMoZAAAAAAAAAA==', '_self': 'dbs/PQFjAA==/colls/PQFjAP5XJMo=/docs/PQFjAP5XJMoZAAAAAAAAAA==/', '_etag': '"34001ee3-0000-2300-0000-627d10dc0000"', '_attachments': 'attachments/', '_ts': 1652363484}
Done.

処理時間:0.23212695121765137 [sec]

データの全件削除

$ python cosmosdb_IoTdummy.py --mode db --db delete
データベースのデータ全削除
B
O
C
E
T
Q
C
K
Done.

処理時間:0.5690500736236572 [sec]

まとめ

これで、CosmosDBのデータ関連の各種テストがやりやすくなるかなぁ、、、、、

参考記事

以下の記事を参考にさせていただきました。感謝申し上げます。
Azure Cosmos DB SQL API client library for Python

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?