[Oracle Cloud] NoSQL Database Cloud Service を Go言語を使ってクイックスタートしてみた

# はじめに

Oracle Cloud Infrastructure(以下OCI)では、NoSQL Cloud Service が提供されています。NoSQL Cloud Service で自分が特に大きい特徴だと思っているのは、次の2点です。

- 完全に管理不要の NoSQL データストア : ユーザー側がインスタンスを意識する必要はありません。可用性、セキュリティパッチなどは、Cloud 側で全てマネージされています。ユーザーが意識するのは、テーブルとテーブルに与える性能、ストレージ容量のみです。
- スキーマ設計不要 : 通常の文字列や数値の他に、JSONデータをストアすることが出来ます。JSON 形式では、スキーマを意識せずにデータを格納できます。



今回の記事は、NoSQL Cloud Service の入門的な内容です。Table を作成して、Go言語からデータを格納・取得する内容を紹介します。



# NoSQL Cloud Service に出てくる概念

リレーショナルデータベースとは違い、一部異なる概念が出てきます。以下の Document で紹介されており、それを抜粋します。

https://docs.cloud.oracle.com/en-us/iaas/nosql-database/doc/table-design.html

- Table : 複数の Row を格納する概念。Table を作成するときに、Column や Data Type を選択します。同じ Table 名は作成できません。
  - サポートしている Data Type : https://docs.cloud.oracle.com/en-us/iaas/nosql-database/doc/table-design.html#GUID-833B2B2A-1A32-48AB-A19E-413EAFB964B8
- Row : テーブルに含まれる行のこと。行の中に、String Type や Number Type, JSON Type といった Filed を持ちます。
- Primary Key : Table には、1つ以上の Primary Key が必要。Primary Keyは、Field の中から選びます。Table を作成する時に Primary Key 指定し、変更は出来ません。Primary Key は、Table 内で一意の値であることが必要です。
- Shard Key : NoSQLのバックエンドで使用している Shard Storage に対して、どのようにデータを格納するかユーザー側でコントロールする概念です。同じ Shard Key を持つ行は、同じ Shard Storage に格納されます。Shard Key は、Primary Key の中から1つ以上選ぶ必要があります。Table 作成時に何も指定しない場合は、すべての Primary Key が Shard Key として選ばれます。
- Index : Table から Row を取得するときに、Index を使用することが出来ます。通常、Table から Row を取得するときは、Primary Key を使用します。Index を使うことで、Primary Key に含まれていない Field を使用して、効率的に Row を取得できます。
- Capacity : Table の読み書き性能、ストレージの容量を指定します。読み書き性能、ストレージの容量は、Table 作成後でも変更が出来ます。
- Time to Live (TTL) : 自動的に Row を削除する期間を指定します。
- Identity Columns : NoSQL Database Cloud Service が自動的に付与する特別な列です。



# NoSQL の Table 作成

それでは、OCI Console で NoSQL の Table を Create していきます。メニューを開いて、Create table を押します。

![1584258286643.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/9cbac86b-6e92-82b1-8cb3-23911a82e66a.png)



各種パラメータを指定して、Create table を押します

- Name : テーブル名を指定
- Primary key columns : Primary Key の列を指定
- Columns : 通常の列を指定
- Reserved Capacity : 読み書き性能、ストレージ容量を指定

![screencapture-console-eu-zurich-1-oraclecloud-nosql-tables-2020-03-15-20_45_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/5b73bd9b-7cc9-bd24-22bc-545dd48b34d7.png)




CREATING になります。

![1584272847991.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/e02d329d-0198-9ea1-4780-cbb9d105cab9.png)



20秒ほどすると、Active に変わりました。詳細画面に移動します

![1584272883203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/e7cac513-4426-f98e-4356-3cc5f22b5278.png)



詳細画面では、次の操作が出来ました。

- 読み書き性能、ストレージ容量の変更
- Column の追加と削除 (Primary Key の変更は不可)
- Index の追加と削除

![1584273012113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/3d1fc8d6-72b3-4978-6985-cac8b73301c9.png)



# SDKの種類

データストアということで、プログラム上で NoSQL を扱っていきます。2020年4月時点では、Java, Python, Node.js, Go の4種類の SDK が提供されています。

Java
https://www.oracle.com/downloads/cloud/nosql-cloud-java-driver-downloads.html

Python
https://nosql-python-sdk.readthedocs.io/en/latest/installation.html

Node.js
https://oracle.github.io/nosql-node-sdk/tutorial-connect-cloud.html

Go
https://github.com/oracle/nosql-go-sdk



# NoSQL GO SDK の Install

自分はGo言語に慣れているので、Go の SDK を使用していきます。Install を行います。Go 自体の導入は適当にぐぐります。

```
go get -u github.com/oracle/nosql-go-sdk
```



# Go Code

実際の Go言語のソースコードです。GitHub でも公開しています。

https://github.com/Sugi275/oci-nosql-connecttest

15行目にある、`iam.NewSignatureProviderFromFile("~/.oci/config", "", "", "ocid1.compartment.oc1..your ocid")` の部分は、適宜環境に合わせて変更してください。

ソースコードを見るとなんとなく処理している内容はわかると思います。

- table01 に、データ(Row)を格納
- 格納したデータ(Row)を取得

```go
package main

import (
	"fmt"
	"os"

	"github.com/oracle/nosql-go-sdk/nosqldb"
	"github.com/oracle/nosql-go-sdk/nosqldb/auth/iam"
	"github.com/oracle/nosql-go-sdk/nosqldb/types"
)

func main() {
	fmt.Println("Process Start")

	provider, err := iam.NewSignatureProviderFromFile("~/.oci/config", "", "", "ocid1.compartment.oc1..your ocid")
	if err != nil {
		fmt.Printf("failed to create new SignatureProvider: %v\n", err)
		return
	}

	cfg := nosqldb.Config{
		Region:                "us-ashburn-1",
		AuthorizationProvider: provider,
	}

	client, err := nosqldb.NewClient(cfg)
	if err != nil {
		fmt.Printf("failed to create a NoSQL client: %v\n", err)
		return
	}

	defer client.Close()

	// テーブル名を指定
	tableName := "table01"

	// データの格納
	mapVals := types.ToMapValue("pk1", 333)
	mapVals.Put("cl1", 444)
	putReq := &nosqldb.PutRequest{
		TableName: tableName,
		Value:     mapVals,
	}
	putRes, err := client.Put(putReq)
	ExitOnError(err, "Can't put single row")
	fmt.Printf("Put row: %v\nresult: %v\n", putReq.Value.Map(), putRes)

	// データの取得
	key := &types.MapValue{}
	key.Put("pk1", 333)
	getReq := &nosqldb.GetRequest{
		TableName: tableName,
		Key:       key,
	}
	getRes, err := client.Get(getReq)
	ExitOnError(err, "Can't get single row")
	fmt.Printf("Got row: %v\n", getRes.ValueAsJSON())

	// Delete the row
	// delReq := &nosqldb.DeleteRequest{
	// 	TableName: tableName,
	// 	Key:       key,
	// }
	// delRes, err := client.Delete(delReq)
	// ExitOnError(err, "Can't delete single row")
	// fmt.Printf("Deleted key: %v\nresult: %v\n", jsonutil.AsJSON(delReq.Key.Map()), delRes)
}

// ExitOnError ExitOnError
func ExitOnError(err error, msg string) {
	if err == nil {
		return
	}
	fmt.Fprintln(os.Stderr, msg, err)
	os.Exit(1)
}
```



実際に実行すると、標準出力には次の出力が表示されます

```
> go run main.go 
Process Start
Put row: map[cl1:444 pk1:333]
result: {"readKB":0,"writeKB":1,"readUnits":0,"existingVersion":null,"existingValue":null,"version":"rO0ABXcsABWDN/or6yVNY416nAez8HTcAAAAABflXngBAwAAAAkAAAABAAACkgD2V9Y=","generatedValue":null}
Got row: {"cl1":444,"pk1":333}
```





# 参考URL

Document
https://docs.cloud.oracle.com/en-us/iaas/nosql-database/index.html

Get Started
https://docs.oracle.com/en/cloud/paas/nosql-cloud/ansct/index.html

Cloud Concepts (概念の説明)
https://docs.cloud.oracle.com/en-us/iaas/nosql-database/doc/cloud-concepts.html