Python3で自宅PCからFirestoreを操作する実験（その１、アプリで使うプレイヤー情報を作ってみる）

#挨拶
こんにちは、B.cosです。
MacOSからFireStoreの操作実験をしてみます。
僕はスマホ用アクションゲームを作っていて、そのためのユーザデータとランキングデータの構成を実装してみようと思います。
Pythonを使うのはたまたま自宅のPCに入っていたから・・・と、それだけでして、書き方に拙いところもあるかと思いますが、最後までお付き合いいただけると幸いです。

いつも通り
**『実は俺もよくわかってねえんだけど、とりあえずこれだけやっておけば使えるぜ』**
という極めていい加減なコンセプトでお送りします。

#参考
Firebaseドキュメント＞Cloud Firestoreβ＞スタートガイド
https://firebase.google.com/docs/firestore/quickstart?hl=ja

#データ構成

####Playersコレクション（プレイヤー情報をストック）

| フィールド       |    説明    |
|:-----------------|:-------------------|
| id             |        自動付与のユニーク文字列        |
| player_name             |        プレイヤー名        |
| code           |       プレイヤーの特定に使用(※1)       |
| date             |        データの作成・更新日時        |


####Scoreコレクション（スコアをストック）

| フィールド       |    説明    |
|:-----------------|:-------------------|
| id             |        自動付与のユニーク文字列        |
| player_id             | スコアを出したプレイヤーのid        |
| player_name             | スコアを出したプレイヤーの名前        |
| character           | 使用キャラ名（※2）       |
| score           | スコア       |
| date             |        データの作成日時        |


※1 今回は適当に数値にしましたが、暗号化した文字列でやったほうが断然いい
※2 キャラクターを選択して遊ぶゲームなので。本来はキャラごとにナンバーを決めておいて、数値をストックしておく方がオススメ。

#Firebaseコンソールでプロジェクトを作成、そして秘密鍵（JSONファイル）をゲット
タイトル通りでしてFirebaseコンソールに行けばすぐわかる話なので、特にここで詳細は話しません。（というか画面構成がいつか変わるかもしれませんし…）
サクッとFirebaseプロジェクトを作って、プロジェクト内の「ProjectOveview」>「プロジェクトの設定」>「サービス アカウント」>「Firebase Admin SDK」で「新しい秘密鍵を生成」ボタンをクリック。
出力されたJSONをダウンロードしましょう。
ダウンロードした秘密鍵は次節の「Firebase Admin Python SDK」で使用します。

#Firebase Admin Python SDKをインストール
ドキュメントの説明を見るとなんだかごちゃごちゃ書いてありますが、これがないとプログラムを書いたマシンとFirebaseがやりとりできませんぜ、ってな話です。
さっさとpipを使ってインストールしちゃいましょう。
コンソールを開いて

```
pip install --user firebase-admin
```

とコマンドを打つだけ。

#Python3を対話型インタプリターで開いて、実験開始
まず定番の、

```
python3
```

で対話型インタプリターを起動です。

#実装
###0.初期化

```
>>> import firebase_admin
>>> from firebase_admin import credentials
>>> from firebase_admin import firestore
>>> import datetime
>>>
>>> # 初期化
>>> # /Users/xxxx/yyyy/zzzz.jsonはダウンロードした秘密鍵のパス
>>> cred = credentials.Certificate('/Users/xxxx/yyyy/zzzz.json')
>>> firebase_admin.initialize_app(cred)
<firebase_admin.App object at 0x@@@@@@@@@>
>>># initialize_app()が実行されることで↑が表示されます。
>>>
>>> db = firestore.client()
>>>
```
以上で初期化完了です。

次にデータを追加してみましょう。

###1.新規作成

```
>>> doc_players_ref = db.collection(u'Players') # コレクション”Players”作成
>>> new_player_ref = doc_players_ref.document() # ”Players”直下でドキュメントを新規で作成
>>> print(new_player_ref.id) # この時点でリファレンスから自動生成されたIDを参照できます。もしアプリで使用する場合はローカルに保存しておきましょう。
Jd3xpud5ZZfr9sRUpupF
>>> new_player_ref.set({
...     u'player_name' : u'日本の米は世界一',
...     u'code' : 1500,
...     u'date' : datetime.datetime.today()
... })
update_time {
  seconds: 1549866051
  nanos: 740152000
}
```


（DBでいうところのテーブルにあたる）コレクションを新規作成（Players）、その直下に（DBでいうところのレコードにあたる）ドキュメントを新規作成、その後、Setメソッドでフィールドを設定していきます。
![スクリーンショット 2019-02-12 2.59.07.png](https://qiita-image-store.s3.amazonaws.com/0/110583/2e0deafa-c1d1-e054-65f4-15e283120589.png)

フィールドはカラムのようなものです（とはいっても、完璧にカラムみたいなものではないのですが・・・それはご自分で調べてください）


###2.データを更新

```
>>> new_player_ref.update({u'u'player_name':u'布団の中から出たくない',u'code':2000})
update_time {
  seconds: 1549866304
  nanos: 781338000
}
```

new_player_refは作成したドキュメントのリファレンスを持ったままなので、「⒉」のようにupdateメソッドでフィールドの中身を編集できます。
![スクリーンショット 2019-02-12 2.59.33.png](https://qiita-image-store.s3.amazonaws.com/0/110583/b9d0eb23-6b13-d8a6-f53d-7d25cba17c5a.png)


###３.なんとなくで（笑）ドキュメントをもう1個作ろうとしたけど・・・

```
>>> new_player_ref.set({
...     u'player_name' : u'日本の米は世界一',
...     u'code' : 3000,
...     u'date' : datetime.datetime.today()
... })
update_time {
  seconds: 1549866382
  nanos: 331016000
}
>>>
```

これは新しく同じ内容のドキュメントを作成しようとして失敗した例で、上述のようにnew_player_refは最初に作ったドキュメントを指したままなので、Setメソッドを使うと「⒉」と同様に内容を編集しただけとなってしまいます。
![スクリーンショット 2019-02-12 3.00.26.png](https://qiita-image-store.s3.amazonaws.com/0/110583/bbc8ac2f-9b35-9eaa-8432-4716576927db.png)


さて、しょぼい失敗のことは忘れて（笑）、新たに三件追加してみましょう。


###4.新しく３件追加

```
>>> new_player_ref = doc_players_ref.document()
>>> new_player_ref.set({
...     u'player_name' : u'島国DNA',
...     u'code' : 1000,
...     u'date' : datetime.datetime.today()
... })
update_time {
  seconds: 1549866710
  nanos: 212669000
}

>>> new_player_ref = doc_players_ref.document()
>>> new_player_ref.set({
...     u'player_name' : u'私を二郎に連れてって',
...     u'code' : 4000,
...     u'date' : datetime.datetime.today()
... })
update_time {
  seconds: 1549866851
  nanos: 901432000
}

>>> new_player_ref = doc_players_ref.document()
>>> new_player_ref.set({
...     u'player_name' : u'88',
...     u'code' : 2400,
...     u'date' : datetime.datetime.today()
... })
update_time {
  seconds: 1549866943
  nanos: 238908000
}
```

コンソールで追加されたことを確認します。
![スクリーンショット 2019-02-12 3.02.25.png](https://qiita-image-store.s3.amazonaws.com/0/110583/06354d7d-8f8d-bec6-ccc6-5569c2600467.png)


###5.次は問い合わせてみましょう。

```
>>> docs = db.collection(u'Players').get()
>>> for doc in docs:
...     print(u'{} => {}'.format(doc.id, doc.to_dict()))
... 
Jd3xpud5ZZfr9sRUpupF => {'date': DatetimeWithNanoseconds(2019, 2, 12, 3, 0, 11, 537650, tzinfo=<UTC>), 'player_name': '日本の米は世界一', 'code': 3000}
Vx2lL0tNt5Ica0Xg99t2 => {'date': DatetimeWithNanoseconds(2019, 2, 12, 3, 2, 8, 742534, tzinfo=<UTC>), 'player_name': '88', 'code': 2400}
hlvLL9NiyLQl4h58PUpm => {'date': DatetimeWithNanoseconds(2019, 2, 12, 3, 1, 55, 694826, tzinfo=<UTC>), 'player_name': '私を二郎に連れてって', 'code': 4000}
kSBsA0X2ojqF2UIHWUfZ => {'date': DatetimeWithNanoseconds(2019, 2, 12, 3, 1, 40, 391426, tzinfo=<UTC>), 'player_name': '島国DNA', 'code': 1000}
>>> 

```

全部表示されましたね。


今回はここまで。

# 次回
Python3で自宅PCからFirestoreを操作する実験（その２、アプリでスコアをアップロードする）
https://qiita.com/bcosizm/items/293b112ab3d305b24cb5

プレイヤー情報を引用した形で、スコアのインサートについてやってみます。