Series: go-firestore

Go で Cloud Firestore を使ってみる2

Cloud Firestore へのデータ書き込みなど。

前回 の続き。

コードは下記に纏めてアップした。

https://gitlab.com/k1350/daybreak_sample/-/tree/firebase_sample/

今回やった部分のみかいつまんで書いていく。

フォームから受け取った値を Firebase に書き込む

type Content struct {
	Text    string    `firestore:"text,omitempty"`
	Created time.Time `firestore:"created,omitempty"`
	Updated time.Time `firestore:"updated,omitempty"`
}

このように Firestore 上のフィールド名を指定した構造体を作って

err := r.ParseForm()
if err != nil {
    log.Fatalln(err)
}
c := Content{
    Text:    r.Form.Get("text"),
    Created: time.Now().UTC(),
    Updated: time.Now().UTC(),
}
_, _, err = client.Collection("posts").Add(ctx, c)
if err != nil {
    log.Fatalln("An error has occurred: %s", err)
}

このようにすると ID は自動採番でデータを追加できる。(データは http/template で作った画面からフォームで受け取っている前提)

時刻については常に特定のタイムゾーンで処理するほうがいいと思うので UTC で追加した。

データ読み込み時のオーダー指定

下記のようにすると created 降順で 10 件取れる。

iter := client.Collection("posts").OrderBy("created", firestore.Desc).Limit(10).Documents(ctx)

ページングについてはまだやっていないが、こんな感じでクエリを作って取得するのは変わりないはず。

データ読み込み時のタイムゾーンについて

常に UTC でデータが取得できるのでこっちでタイムゾーンを変える。

本当はブラウザのタイムゾーンで書き換えるようなことをしたかったが、とりあえずサーバーサイドで JST に変えてみる。

time.Local = time.FixedZone("Local", 9*60*60)
jst, _ = time.LoadLocation("Local")

iter := client.Collection("posts").OrderBy("created", firestore.Desc).Limit(limit).Documents(ctx)

var posts []map[string]interface{}
for {
    doc, err := iter.Next()
    if err == iterator.Done {
        break
    }
    if err != nil {
        log.Fatalln("Failed to iterate: %v", err)
    }
    item := doc.Data()
    v := make(map[string]interface{})
    v["text"] = item["text"]
    v["created"] = item["created"].(time.Time).In(jst)
    v["updated"] = item["updated"].(time.Time).In(jst)
    posts = append(posts, v)
}

こんな感じで取得した doc.Data() の時刻データを time.Time にキャストした上でを JST に変えて別の Map に格納しなおしてみた。もっとすっきりした書き方があるような気もする。

以上