データベースに「保存」を行った日時を記録するフィールドを使って、差分更新を行う。 データベースの丸ごとのダウンロードではないので、通信量の節約などができる.
Python のプログラム作成には、PyCharmなどが便利である.
以下,Windows でインストール済みであるものとして説明を続ける.
pip install -U firebase-admin
※ 以上の手順は、「Python で Google Firebase の Cloud Firestore (クラウド・ファイアストア)を使ってみる」で説明している.
datetime 型の created_at フィールドを含むようなドキュメントを作る
さて、「created_at」は、ドキュメントがデータベースに挿入された日時という意味。 あとから入ったドキュメントは、前に入ったドキュメントの「created_at」よりも新しい日時の値を持つ。
例えば、次のように。
「H:/my-project-abcde-firebase-adminsdk-q53ez-5d420dbcf2.json」のところは、先ほどダウンロードした JSON ファイル名にすること。
「u'time', u'>', datetime(2019,4,13,3,10,0)」は、日時(Python の datetime) の比較
import datetime
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate('H:/my-project-abcde-firebase-adminsdk-q53ez-5d420dbcf2.json')
app = firebase_admin.initialize_app(cred)
db = firestore.client()
ref = db.collection(u'docs')
a = ref.where(u'created_at', u'>', datetime.datetime(2019,4,8,9,30,0))
docs = a.stream()
for doc in docs:
print(u'{} => {}'.format(doc.id, doc.to_dict()))
import datetime
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate('H:/my-project-abcde-firebase-adminsdk-q53ez-5d420dbcf2.json')
app = firebase_admin.initialize_app(cred)
db = firestore.client()
ref = db.collection(u'docs')
# last を設定、「created_at」の値が「last」以降のものをダウンロード
last = datetime.datetime(2019,4,8,0,30,0, 0,datetime.timezone.utc)
a = ref.where(u'created_at', u'>', last)
docs = a.stream()
new_last = last
for doc in docs:
print(u'{} => {}'.format(doc.id, doc.to_dict()))
# 確認のため「last以降のデータであるかを表示」
print(last < doc.to_dict()['created_at'])
# その中の created_at で最も最新のものを調べる
if ( new_last < doc.to_dict()['created_at'] ):
new_last = doc.to_dict()['created_at']
タイマーは「5」秒に設定。5秒ごとにダウンロードして、表示を繰り返す
ダウンロードのたびに、まるごとダウンロードはしたくない。差分(新しいデータ)のみをダウンロードして、すでにダウンロード済みのデータに付け加える(更新)の操作としたい。
そこで、ダウンロードごとに、ダウンロードしたドキュメントの中の「created_at で最も最新のもの」を調べる。 そして、その次のダウンロードでは、「created_at で最も最新のもの」引く10秒以降のものをダウンロードする (「10」と決めているのに、特に根拠はない. create_at を付けるシステムの側で -10秒の変動はありえるかも、と勝手に決めているだけ)
サイト内の関連ページ 一定間隔で処理の繰り返し
import time
import threading
import datetime
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate('H:/my-project-abcde-firebase-adminsdk-q53ez-5d420dbcf2.json')
app = firebase_admin.initialize_app(cred)
db = firestore.client()
ref = db.collection(u'docs')
# base を設定、「created_at」の値が「base」以降のものをダウンロード
base = datetime.datetime(2019,4,8,0,30,0, 0,datetime.timezone.utc)
last = base
# ダウンロードしたデータを置くためののオブジェクト。最初は空
cache = {}
def worker():
global last
global cache
a = ref.where(u'created_at', u'>', last)
docs = a.stream()
new_last = last
for doc in docs:
# print(u'{} => {}'.format(doc.id, doc.to_dict()))
# 確認のため「last以降のデータであるかを表示」
print(last < doc.to_dict()['created_at'])
# ダウンロードしたデータを保存
cache[doc.id] = doc.to_dict()
# その中の created_at で最も最新のものを調べる
if ( new_last < doc.to_dict()['created_at'] ):
new_last = doc.to_dict()['created_at']
print("cache data")
print(cache)
if ( last < ( new_last - datetime.timedelta(0,10) ) ):
last = new_last - datetime.timedelta(0,10)
def mainloop(time_interval, f):
now = time.time()
while True:
t = threading.Thread(target=f)
t.start()
t.join()
wait_time = time_interval - ( (time.time() - now) % time_interval )
time.sleep(wait_time)
# 5秒間隔
mainloop(5, worker)