GCPのサービスをいろいろ試してみる(Cloud DataStore)

使い所を間違えなければ便利。





概要



https://cloud.google.com/datastore/docs/?hl=ja
NoSQL
トランザクションをサポートしていたりSQLと似た公文のGQLが使えるのが特徴。



ダッシュボードからCloud Data Storeにデータ(エンティティ)を追加する



以下のクイックスタートを試してみる。
https://cloud.google.com/datastore/docs/quickstart?hl=ja

プロジェクトを選択していた場合ロケーションは表示されない。


https://console.cloud.google.com/datastore/entities/query/kind
からエンティティを作成できる。

RDBでいうところの
名前空間はスキーマ
種類はテーブル名
キー識別子は主キー
プロパティはカラム
エンティティはデータ
といったところだろうか。

エンティティ作成画面では種類を先に入力していないとプロパティがクリアされてしまう。せっかく入力したのに...

種類を入力してプロパティを追加して作成ボタンを押下したら、データが追加されクエリを利用してフィルタすることができるようになる。

データ追加が面倒すぎるのでできればスプレッドシートなどから引っ張れるようにしたい。




GoプログラムからCloud Data Storeにデータ(エンティティ)を追加する



プログラムからデータ操作できるようにしたい。

https://cloud.google.com/datastore/docs/concepts/entities?hl=ja
https://cloud.google.com/datastore/docs/datastore-api-tutorial?hl=ja
がドキュメント

コマンド

go get github.com/GoogleCloudPlatform/golang-samples/datastore/tasks

でサンプルが取得できる。あるいはどこかのタイミングで取得済みかもしれない。

ターミナル(PowerShell)からtasksディレクトリに移動して
go run tasks.go
で確認可能。

ローカルから操作する場合認証が必要のようだ。
https://cloud.google.com/docs/authentication/getting-started

ダッシュボードの APIとサービス → 認証情報 から
https://console.cloud.google.com/apis/credentials

jsonファイルをダウンロードして以下のコマンド(PowerShell)
$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\[FILE_NAME].json"

上記は環境変数:GOOGLE_APPLICATION_CREDENTIALSにダウンロードしたファイルのパスを設定している(一時的)

サンプルを動かす場合以下も必要。project-idはGCP(GAE)のプロジェクトID
$env:DATASTORE_PROJECT_ID="project-id"

以上サンプルの動作をまとめるとローカルからデータ追加する手順は。

コマンドからgcloudにログイン
gcloud auth login
普段から使用していれば恐らく認証済み

datastore.NewClient 時はprojectIDを指定する。
プロジェクトIDはダッシュボードから

認証情報を設定する。
下記はPowerShellの例。
$env:GOOGLE_APPLICATION_CREDENTIALS="D:\dl\aaaa-09fc5aa8ed9e1e.json"
jsonファイルはprojectにでも入れて(ただし公開しないように)おいたほうがいいかもしれない。

ちなみにローカルサーバで動かすときにクラウド上のデータストアを参照したい場合

env_variables:
  GOOGLE_APPLICATION_CREDENTIALS: D:\dl\aaaa-09fc5aed9e1e.json

のようにすると良い

あるいは上記コマンドは一時的に環境変数に設定しているだけなので永続化するか。
ただそうするとプロジェクトを切り替えるのが面倒になってしまう。


下記がシンプルなデータ追加のサンプルコード

script.go

package main

import (
 "context"
 "fmt"

 // Imports the Google Cloud Storage client package.
 "cloud.google.com/go/datastore"
)

// TestModel データモデル
type TestModel struct {
 Test string
}

func main() {
 entity := &TestModel{
  Test: "Test",
 }
 ctx := context.Background()
 // ダッシュボードから確認できるプロジェクトIDを指定する
 projectID := "projectID"
 client, err := datastore.NewClient(ctx, projectID)
 if err != nil {
  fmt.Printf("datastore client 作成に失敗: %v", err)
 }
 // DataStore のkind
 kind := "kindName"
 key := datastore.IncompleteKey(kind, nil)

 if _, err := client.Put(ctx, key, entity); err != nil {
  fmt.Println(err)
 }
}

go run script.go

ダッシュボードにアクセスして
https://console.cloud.google.com/datastore/entities

"kindName"でフィルタしてみるとデータが登録されていることがわかる。

datastore

特に制御等をかけていないので実行した数だけデータが登録される。
ここまで出来れば後は自由にデータを投入できる。

ちなみに複数のデータを投入したい場合


// DataStore のkind
 projectID := "projectID "
 kind := "kindname"
 ctx := context.Background()

 client, err := datastore.NewClient(ctx, projectID)
 if err != nil {
  fmt.Printf("datastore client 作成に失敗: %v", err)
 }
 data := strings.Split(test, "\n")
 var keys []*datastore.Key
 // fmt.Println((len(data)))
 var entities []BattleModel
 for r := 0; r < len(data); r++ {
  rowData := strings.Split(data[r], "\t")
  // fmt.Println(data[r])
  entity := TestModel{}
  entity.a = rowData[0]
  entity.b = rowData[1]

  entities = append(entities, entity)
  key := datastore.IncompleteKey(kind, nil)
  keys = append(keys, key)
 }

 _, err = client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
  _, err := tx.PutMulti(keys, entities)
  return err
 })

といった具合になる(keysの型がわからなくてハマった)
keyをエンティティごとに指定できるということは全く違うデータも投入できそうだ(恐らくやらない)

rpc error: code = InvalidArgument desc = operating on too many entity groups in a single transaction.

1トランザクションで変更可能なデータは25までという制限があるようだ

https://qiita.com/hichika/items/180f1820caf05b275a22#operating-on-too-many-entity-groups-in-a-single-transaction




GoプログラムからCloud Data Storeにのデータをクエリする



プログラムからクエリする方法は以下。それほど難しくはない
https://cloud.google.com/datastore/docs/concepts/queries?hl=ja#datastore-datastore-basic-query-go

以下にリファレンスが載っている(英語)
https://godoc.org/cloud.google.com/go/datastore


list.go

package main

import (
 "context"
 "fmt"
 "time"

 // Imports the Google Cloud Storage client package.
 "cloud.google.com/go/datastore"
)

// TestrModel データモデル
type TestModel struct {
 Test     time.Time
}

func main() {

 ctx := context.Background()
 // ダッシュボードから確認できるプロジェクトIDを指定する
 projectID := "projectID"
 client, _ := datastore.NewClient(ctx, projectID)
 kind := "kind"
 q := datastore.NewQuery(kind).Limit(100).Order("created")
 var entities []TestModel
 client.GetAll(ctx, q, &entities)
 fmt.Println(entities)
}

上記種類"kind"から100件取得してcreatedでソートする処理になる。
Orderはそのままだと昇順。.Order("-created")のようにプロパティ名に-をつけると降順になる。

Filterを使用することで絞り込みもできる。
FilterとOrderが同時に使用する場合まずFilterしたプロパティでOrderを指定しないといけないようだ。。

いろいろ試してみて追記予定


2019年1月24日木曜日