前回はGCPのNoSQLサービス、Cloud Firestoreの使い始め、GUIでの操作方法をについてご紹介しました。
www.true-fly.com
本日のテーマはこちら!
今回はプログラムからCloud Firestoreのデータを操作したり検索したりして、自分たちのアプリケーションに導入できるように進めていこうと思います!
準備
ディレクトリ構成
以下のディレクトリ構成で検証を進めていきます。
main.py
がPythonプログラム、
service_account.json
がサービスアカウントの認証情報です。
. ├── main.py └── service_account.json
サービスアカウントの設定をする
Cloud Firestoreに限らず、プログラムでGCPのプロダクトを操作するにはサービスアカウントが必要です。
まずはサービスアカウントを作成します。
GCPコンソールから、[IAMと管理] > [サービスアカウント] > [サービスアカウントを作成]と進みます。
名前や説明は任意です。
その後、認証情報(秘密鍵)をservice_account.json
というファイル名でローカルに保存しておきます。
ライブラリのインストール
pipで以下のライブラリをインストールしておきます。
pip install google-cloud-firestore
環境変数の設定
service_account.json
があるディレクトリで以下を実行します。プログラム上で参照する環境変数です。
export PROJECT_ID=自分のGCPのプロジェクトID export GOOGLE_APPLICATION_CREDENTIALS="$PWD/service_account.json"
コレクションを作成する
Cloud FirestoreのWebUIで予めコレクションを作成しておきます。
今回はtrue-flyというコレクションを作成しました。
最低ドキュメントが1つ必要なので、空で作成しています。
ドキュメントを作成する
true-flyコレクションにドキュメントをPythonで作成していきます。
db.collection('true-fly')
で、true-flyというコレクションを指定しています。
7行目のdoc_ref.set()
で、dictをパラメータに入れて実行すると、Cloud Firestoreにドキュメントが追加されます。
今回は当ブログの記事のRSSデータを登録してみます。
import os from google.cloud import firestore db = firestore.Client(project=os.environ['PROJECT_ID']) doc_ref = db.collection('true-fly').document() doc_ref.set( { 'title': '【超入門】GCPのNoSQL、Cloud Firestoreを使ってみる', 'url': 'https://www.true-fly.com/entry/2021/09/01/070000', 'published_at': '2021-09-01 07:00:00', 'categories': ['GCP', 'Cloud Firestore'], } )
結果をWebUIで確認します。無事データが入りました!
ドキュメントのIDは自動で割り振られます。IDを自分で指定したいときは、db.collection('true-fly').document('ここでIDを指定')
で設定できます。
import os from google.cloud import firestore db = firestore.Client(project=os.environ['PROJECT_ID']) doc_ref = db.collection('true-fly').document(’00001’) doc_ref.set( { 'title': 'データエンジニアなら知っておきたい、NoSQLってなに?', 'url': 'https://www.true-fly.com/entry/2021/08/31/070000', 'published_at': '2021-08-31 07:00:00', 'categories': 'IT読み物' } )
ドキュメントの一覧を取得する
ドキュメント一覧を取得したい場合は、db.collection('true-fly').stream()
で取得できます。配列で返ってくるので、forで回して、1行ずつdictに変換して標準出力してみます。
import os from google.cloud import firestore db = firestore.Client(project=os.environ['PROJECT_ID']) docs = db.collection('true-fly').stream() for doc in docs: print(doc.to_dict())
結果
$ python main.py {'published_at': '2021-08-31 07:00:00', 'categories': 'IT読み物', 'url': 'https://www.true-fly.com/entry/2021/08/31/070000', 'title': 'データエンジニアなら知っておきた い、NoSQLってなに?'} {'categories': 'IT読み物', 'url': 'https://www.true-fly.com/entry/2021/08/31/070000', 'title': 'データエンジニアなら知っておきたい、NoSQLってなに?', 'published_at': '2021-08-31 07:00:00'} {}
ドキュメントを検索する
当ブログのRSSデータをある程度追加した上で、今度はドキュメントを検索してみます。
ドキュメントを検索するには、db.collection('true-fly').where(演算子).stream()
でできます。
例えば文字列の完全一致検索であれば以下のとおりです。
import os from google.cloud import firestore db = firestore.Client(project=os.environ['PROJECT_ID']) docs = db.collection('true-fly').where('title', '==', 'Airflow Breezeを使い、Windows10上でAirflowを動かす').stream() for doc in docs: print(doc.to_dict())
結果
$ python main.py {'url': 'https://www.true-fly.com/entry/2021/07/18/180000', 'published_at': '2021-07-18 18:00:00', 'title': 'Airflow Breezeを使い、Windows10上でAirflowを動かす', 'categories': ['AIrflow', 'Python']}
クエリ演算子はこちらのドキュメントに記載されています。
配列内の要素で検索は、array_contains
演算子でできました。
import os from google.cloud import firestore db = firestore.Client(project=os.environ['PROJECT_ID']) docs = db.collection('true-fly').where('categories', 'array_contains', 'Python').stream() for doc in docs: print(doc.to_dict())
結果
$ python main.py {'categories': ['GCP', 'Cloud Functions', 'Python'], 'title': '【Google Cloud Functions】Pythonでサーバレスサービスに入門してみる【FaaS】', 'published_at': '2021-08-25 07:00:00', 'url': 'https://www.true-fly.com/entry/2021/08/25/070000'} {'url': 'https://www.true-fly.com/entry/2021/08/23/073000', 'published_at': '2021-08-23 07:30:00', 'categories': ['Python入門', 'Python'], 'title': '【Python入門】コメ ントとdocstring'} {'title': 'Airflow Breezeを使い、Windows10上でAirflowを動かす', 'url': 'https://www.true-fly.com/entry/2021/07/18/180000', 'published_at': '2021-07-18 18:00:00', 'categories': ['AIrflow', 'Python']} {'title': '【Cloud Functions】Cloud Schedulerを使って、サーバレス関数をスケジュール実行する【FaaS】', 'categories': ['GCP', 'Cloud Functions', 'Python'], 'published_at': '2021-08-26 07:00:00', 'url': 'https://www.true-fly.com/entry/2021/08/26/070000'}
文字列の部分一致のような高度なクエリは実行できないようです。このへんがNoSQLの弱みかもしれません。
まとめ
以上、今日はCloud FirestoreをPythonで操作する方法についてご紹介しました。
データの登録はスキーマレスなのでdictで自由に登録できたり、全件データを取得するのも関数一つでできるので、複雑なコードを書かなくともデータの出し入れができるのが非常に魅力的です。
次回はGCPのサーバレスサービス、Cloud FunctionsでCloud Firestoreに接続し、サーバレスでデータの読み込み、書き込みを実現する方法についてご紹介しようと思います!