[Golang]MongoDBを使ってみよう-Gopherへの道③

はじめに

こんにちは、Golangの記事第三弾です。
今回は Golang + MongoDB を使用する機会がありましたので、さっそく調べてみました!
ここでは、MongoDBの簡単な概要と、MongoDBの公式ドライバを使用した簡単なCRUD操作について見ていきます。
今回はReadとCreateのみ紹介ですが、公式のUsageから他も同様に確認できます。

MongoDB

MongoDBは、NoSQLのうち、ドキュメント指向のデータベースです。
RDBMSとの大きな違いとして、テーブルのように事前にデータ構造を決定しておかなくてもよい点などが挙げられます。
あとから自由にスキーマを変更できるので、APIの仕様変更などがあっても柔軟に対応できるようになっています。
シンプルで自由度の高いデータ構造も、静的型付けのGolangとは相性が良いように思います。

ドライバのインストール

公式のドキュメントを参考にします
https://docs.mongodb.com/drivers/go/current/quick-start/

go get go.mongodb.org/mongo-driver/mongo

接続の例

package main

import (
"context"
"fmt"

"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)

// Connection URI
const uri = "<<mongoDB-URI>>"

func main() {
// Create a new client and connect to the server
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))

if err != nil {
panic(err)
}
defer func() {
if err = client.Disconnect(context.TODO()); err != nil {
panic(err)
}
}()

// Ping the primary
if err := client.Ping(context.TODO(), readpref.Primary()); err != nil {
panic(err)
}

fmt.Println("Successfully connected and pinged.")
}

ドキュメントの取得

FindOne

type respData struct {
Id primitive.ObjectID `json:"id" bson:"_id"`
Name string `json:"name" bson:"name"`
}

func main() {
coll := client.Database("<<dbName>>").Collection("<<collectionName>>")

var result respData
err = coll.FindOne(context.TODO(), bson.D{{"<<fieldName>>", "hoge"}}).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
// This error means your query did not match any documents.
return
}
panic(err)
}
}

collection.FindOneの返り値は*mongo.SingleResultの型ですが、
Decodeが構造体にマッピングしてくれます。

Find (Multiple Documents)

type respData struct {
Id primitive.ObjectID `json:"id" bson:"_id"`
Name string `json:"name" bson:"name"`
}

func main() {
coll := client.Database("<<dbName>>").Collection("<<collectionName>>")

filter := bson.D{{"<<fieldName>>", bson.D{{"$eq", "hoge"}}}}

cur, err := coll.Find(context.TODO(), filter)
if err != nil {
panic(err)
}

for cur.Next(context.TODO()) {
var res respData
cur.Decode(&res)
fmt.Println(res)
}
}

複数ドキュメントの取得ができるFindは返り値が*mongo.Cursorです。
こちらもDecodeでマッピング可能。

ドキュメントの追加

InsertOne

func main() {
coll := client.Database("<<dbName>>").Collection("<<collectionName>>")

doc := bson.D{{"title", "Record of a Shriveled Datum"}, {"text", "No bytes, no problem. Just insert a document, in MongoDB"}}
result, err := coll.InsertOne(context.TODO(), doc)
if err != nil {
panic(err)
}
}

InsertMany

docs := []interface{}{
bson.D{{"title", "Record of a Shriveled Datum"}, {"text", "No bytes, no problem. Just insert a document, in MongoDB"}},
bson.D{{"title", "Showcasing a Blossoming Binary"}, {"text", "Binary data, safely stored with GridFS. Bucket the data"}},
}
result, err := coll.InsertMany(context.TODO(), docs)
if err != nil {
panic(err)
}

おわりに

MongoDBの操作について簡単にまとめてみました。
MongoDBは、bsonなど独特なデータ構造を使用する、RDBMSのような高度な結合処理が難しい、などわかりにくい部分もありましたが
Golang + MongoDB の組み合わせでは、高速な検索や柔軟なスキーマ変更など、開発に便利な感触がありました。
Aggregationなど高度な操作も、機会があればまとめたいと思います。
ありがとうございました。

備考

前へ

【初心者必見!】Notionについて知ろう!Notionを使えばどんなことができるの?

次へ

NGINXのドキュメントルートをいろいろ変更してみた