LoginSignup
0
1

More than 1 year has passed since last update.

FirestoreのTimestamp型をStartAfterするときの注意点

Last updated at Posted at 2022-07-08

FirestoreのTimestamp型について

記事の内容

今回は業務中に詰まったFirestoreのtimestamp型の取得について書いていきます。
結論を言っておくと、取得の際はnanoSecondまで意識したほうがいいです。
※Firestoreに直接データを追加したからかもしれません、原因検証は不十分です。

環境

Laravel 9 Mysql 8 Ubuntu

Timestamp型の中身

FirestoreのdocumentからTimestamp型の中身を取り出すと以下のような形になっています。

Google\Cloud\Core\Timestamp ^{
-value: DateTimeImmutable @1657260000 {
  date: 2022-07-08 06:00:00.651 +00:00
}
-nanoSeconds: 651000000

上記のデータは日本時間の「2022年7月8日 14:00:00」です。
取得の際は日本時間でひっかけて取得できますが、手元に来るときにUTCに変換されます。(設定でどうにかなるんですかね?)

ここでの注目ポイントはdateが「Y-m-d H : i : s .u」とFirestoreで設定していないnanoSecondが付いていることです。
Firestoreに直接テストデータを作成したからかは不明ですが、「2022-07-08 14:00:00」と設定したにも関わらず、nanoSecondが付いていました。

nanoSecondがあると何がまずいのか

これがあるとstartAfterではじくことができない場合があります。
MySqlを使用してditetimeに「Y-m-d H:i:s」形式で時間を保存していました。
ここでDB内の最新データ以降のものをFirestoreから取得しようとすると重複が発生する可能性があります。

とりあえずFirestore上にtimestamp型のcreated_atが保存されているとします。
DB内の最新データを$latest = 2022-07-08 14:00:00;とした場合、以下のような感じで取得すると思います。

$docRef = $this->firestore->database()->collection('test');
$datetime = new Datetime($latest , new DateTimeZone('Asia/Tokyo'));
$query = $docRef->orderBy('created_at')->startAfter([$latest])
$documents = $query->get()

この時、Firestoreに保存されている「2022年7月8日 14:00:00」のデータは取得したくないですが、謎のnanoSecondによって「$latest <= Firestore上のデータ」になるので取得できてしまいます。

解決策

  1. DiteTime型のカラムにnanoSecondを3桁分格納できるように変更。
  2. Firestoreのtimestamp型には__toString()という関数が使用できるので、Carbon::create($firestore_time->__toString())としてそのままDBに保存する
    ※__toString()はnanoSecondも含めて時間を返してくれます。

まとめ

Firestoreのtimestamp型はnanoSecondがあるので注意しましょう。
もしかしたらLaravelやアプリ側から登録する際はnanoSecondがないのかもしれませんが、詳しくはまだ未検証です。
documentSnapshotのcreateTime()やupdateTime()はnanosecond持ちですがwhereなどはかけられないので、fieldの値には警戒しておいたほうがいいと思います。

0
1
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
0
1