0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Firestoreをgoの構造体で扱う

Posted at

概要

GoでFirestoreを扱う際に、構造体を利用したかったのだがその取扱いについて詳細な記載がなかったのでいろいろと試してみました。

ただし今回の記事は、調査するための基盤づくりとしての要素が強いので調査内容自体は簡易的なものです。自身のユースケースに合わせて今後も調査できればと思います。

ちなみに今回は、構造体内でポインタを使った際の動作について検証しました。

(ある程度Firestoreの操作を知っている人向けになってしまうことをお許しください)

始めるにあたって

PlayGroundで動作可能な範疇を超えていたのでGithubでレポジトリを作成しました。簡単な使い方を紹介していたりしていますが、調査が目的なため殴り書きです。悪しからず。

調査内容

概要でも示した通り、Firestoreでドキュメントを作成する際や取得する際にどのような構造体であれば、なんのデータが得られるのかを確認してみました。

具体的には以下のようなケースです。(今回の検証に利用した構造体です)

type City struct {
	Name string   `firestore:"name"`
	Tags []string `firestore:"tags"`
	Pop  int64    `firestore:"population"`
}

type PC struct {
	Name *string  `firestore:"name"`
	Tags []string `firestore:"tags"`
	Pop  *int64   `firestore:"population"`
}

PCPointerCityの略称です。
同じフィールド名に対して、ポインタで定義しているかそうでないかが異なっています。
こうした場合、特にポインタで定義した場合どのようになるか以下の観点で気になりました。

今回の検証対象

  • 新規書込時にnilであれば書き込み対象にならないのか
  • 読み込み時に存在しないフィールドを取得する際の挙動はどのようになるのか
  • ([]stringで構造体として受け取れるのか否か)

検証していないこと

  • 更新の際nilなフィールドは更新されないのか、はたまた削除されるのか

調査

今回は四つの流れで検証しました。

  • Do0
    • すべての項目が埋められたCity構造体でDocCreate
    • City構造体でDocの内容をGet
    • PC構造体でDocの内容をGet
  • Do1
    • 一部の項目(Nameのみ)が埋められたCity構造体でDocCreate
    • City構造体でDocの内容をGet
    • PC構造体でDocの内容をGet
  • Do2
    • すべての項目が埋められたPC構造体でDocCreate
    • City構造体でDocの内容をGet
    • PC構造体でDocの内容をGet
  • Do3
    • すべての項目が埋められたPC構造体でDocCreate
    • City構造体でDocの内容をGet
    • PC構造体でDocの内容をGet

基本的には作成、読み込みの手順を踏んでおり、四つの手法では作成の部分のみ異なっています。

関連するソースコードは以下のようになります。Githubからご確認ください。

  • cmd/structs/main.go
  • internal/structs/action.go
  • internal/structs/dos.go
  • internal/structs/structs.go

結果

それぞれの手順で実行した結果を以下に示します。
一番上にFireStore内での構成。
その下にCityで取得した際の結果とPCで取得した際の結果を示しています。

Do0
Name:  City Full
*  users/
*      userid0/
*        tags: ([]interface {} -> [hello world haha])
*        population: (int64 -> 56)
*        createdAt: (time.Time -> 2021-07-30 11:57:13.986231 +0000 UTC)
*        name: (string -> sasakuna)
*        updatedAt: (time.Time -> 2021-07-30 11:57:13.986231 +0000 UTC)
(end)

Name:  Data To City
City:  &{sasakuna [hello world haha] 56}

Name:  Data To PC
City:   interface{}(
+       &structs.PC{Name: &"sasakuna", Tags: []string{"hello", "world", "haha"}, Pop: &56},
  )

Do1
Name:  City Partial
*  users/
*      userid0/
*        population: (int64 -> 0)
*        tags: (Nil -> <nil>)
*        createdAt: (time.Time -> 2021-07-30 11:57:14.002157 +0000 UTC)
*        name: (string -> sasakuna)
*        updatedAt: (time.Time -> 2021-07-30 11:57:14.002157 +0000 UTC)
(end)

Name:  Data To City
City:  &{sasakuna [] 0}

Name:  Data To PC
City:   interface{}(
+       &structs.PC{Name: &"sasakuna", Pop: &0},
  )
Do2
Name:  PC Full
*  users/
*      userid0/
*        name: (string -> sasakuna)
*        updatedAt: (time.Time -> 2021-07-30 11:57:14.016314 +0000 UTC)
*        tags: ([]interface {} -> [hello world haha])
*        population: (int64 -> 56)
*        createdAt: (time.Time -> 2021-07-30 11:57:14.016314 +0000 UTC)
(end)

Name:  Data To City
City:  &{sasakuna [hello world haha] 56}

Name:  Data To PC
City:   interface{}(
+       &structs.PC{Name: &"sasakuna", Tags: []string{"hello", "world", "haha"}, Pop: &56},
  )
Do3
Name:  PC Partial
*  users/
*      userid0/
*        createdAt: (time.Time -> 2021-07-30 11:57:14.030879 +0000 UTC)
*        name: (string -> sasakuna)
*        updatedAt: (time.Time -> 2021-07-30 11:57:14.030879 +0000 UTC)
*        tags: (Nil -> <nil>)
*        population: (Nil -> <nil>)
(end)

Name:  Data To City
City:  &{sasakuna [] 0}

Name:  Data To PC
City:   interface{}(
+       &structs.PC{Name: &"sasakuna"},
  )

まとめ

今回の結果から以下のようなことがわかりました。

値を割当てなかった際の挙動

タイプ Create Get
デフォルト値が保管される デフォルト値が代入される
ポインタ Nilとして保管される nilのまま

フィールド値そのものが存在しないようにふるまうわけではなさそう。

感想

よくよく考えたら、ソースコードみれば分かったのでは....?
今後も手っ取り早く動作を確認するのに使わせてもらいます。

というか今回の最大の成果は、Firestore内のデータを可視化したことでは?

あとがき

書いていて、タグ情報ってほかに追加できないのかなって思っていたら、omitemptyという項目がありました。
これを追加すると0値の時にそのフィールドをエンコード対象としないことができるらしく、恐らく多くの人はこちらを使っていることと思います。(これの少し下あたり)
ただ、0を代入することができないという側面もあるので、完全に無駄というわけではなさそう。

ということで、今回の成果は簡単にFirestoreの挙動調査ができるレポジトリをGithubにあげたという点に落ち着きました。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?