title: 【転載】Go 言語による mongoDB 操作
date: 2021-08-09 16:38:33
comment: false
toc: true
category:
- Golang
tags: - 转载
- Go
- MongoDB
- Mongo
- 操作
本文は以下から転載されています:Go 言語による mongoDB 操作 | 李文周のブログ
mongoDB は現在比較的人気のある分散ファイルストレージに基づくデータベースで、関係データベースと非関係データベース (NoSQL) の間に位置する製品であり、非関係データベースの中で最も機能が豊富で、関係データベースに最も似ています。
mongoDB の紹介#
mongoDBは現在比較的人気のある分散ファイルストレージに基づくデータベースで、関係データベースと非関係データベース (NoSQL) の間に位置する製品であり、非関係データベースの中で最も機能が豊富で、関係データベースに最も似ています。
mongoDB では、1 つのデータをドキュメント(document)として保存し、データ構造はキーと値(key-value)ペアで構成されています。ドキュメントは、通常のプログラミングで使用される JSON オブジェクトに似ています。ドキュメント内のフィールド値には、他のドキュメント、配列、およびドキュメントの配列を含めることができます。
mongoDB の関連概念#
mongoDB の関連概念は、私たちがよく知っている SQL の概念と比較すると以下のようになります:
MongoDB 用語 / 概念 | 説明 | SQL 用語 / 概念との比較 |
---|---|---|
database | データベース | database |
collection | コレクション | table |
document | ドキュメント | row |
field | フィールド | column |
index | index | インデックス |
primary key | 主キー MongoDB は自動的に_id フィールドを主キーに設定します | primary key |
mongoDB のインストール#
ここではコミュニティ版をダウンロードしてインストールします。公式ダウンロードページ。 上記のリンクを開いたら、対応するバージョン、オペレーティングシステムプラットフォーム(一般的なプラットフォームはすべてサポートされています)およびパッケージタイプを選択し、Download ボタンをクリックしてダウンロードします。
ここで補足説明しますが、Windows プラットフォームにはZIP
とMSI
の 2 つのパッケージタイプがあります: * ZIP:圧縮ファイル版 * MSI:実行可能ファイル版、クリックして「次へ」を選択してインストールできます。
macOS プラットフォームでは、上記のウェブページからTGZ
ファイルをダウンロードするほか、Homebrew
を使用してインストールすることもできます。
詳細なインストール手順については、公式インストールガイドを参照してください。Linux、macOS、Windows の 3 つの主要プラットフォームのインストール手順が記載されています。
mongoDB の基本使用#
mongoDB データベースの起動#
Windows#
"C:\Program Files\MongoDB\Server\4.2\bin\mongod.exe" --dbpath="c:\data\db"
Mac#
mongod --config /usr/local/etc/mongod.conf
または
brew services start [email protected]
クライアントの起動#
Windows#
"C:\Program Files\MongoDB\Server\4.2\bin\mongo.exe"
Mac#
mongo
データベースの一般的なコマンド#
show dbs;
:データベースを表示
> show dbs;
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
use q1mi;
:指定したデータベースに切り替えます。存在しない場合は作成されます。
> use q1mi;
switched to db q1mi
db;
:現在のデータベースを表示。
> db;
q1mi
db.dropDatabase()
:現在のデータベースを削除
> db.dropDatabase();
{ "ok" : 1 }
データセットの一般的なコマンド#
db.createCollection(name,options)
:データセットを作成
- name:データセット名
- options:オプションパラメータ、メモリサイズとインデックスを指定。
> db.createCollection("student");
{ "ok" : 1 }
show collections;
:現在のデータベース内のすべてのコレクションを表示。
> show collections;
student
db.student.drop()
:指定したデータセットを削除
> db.student.drop()
true
ドキュメントの一般的なコマンド#
ドキュメントを 1 つ挿入:
> db.student.insertOne({name:"小王子",age:18});
{
"acknowledged" : true,
"insertedId" : ObjectId("5db149e904b33457f8c02509")
}
複数のドキュメントを挿入:
> db.student.insertMany([
... {name:"張三",age:20},
... {name:"李四",age:25}
... ]);
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5db14c4704b33457f8c0250a"),
ObjectId("5db14c4704b33457f8c0250b")
]
}
すべてのドキュメントをクエリ:
> db.student.find();
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "小王子", "age" : 18 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "張三", "age" : 20 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "李四", "age" : 25 }
age>20 のドキュメントをクエリ:
> db.student.find(
... {age:{$gt:20}}
... )
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "李四", "age" : 25 }
ドキュメントを更新:
> db.student.update(
... {name:"小王子"},
... {name:"老王子",age:98}
... );
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.student.find()
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "老王子", "age" : 98 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "張三", "age" : 20 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "李四", "age" : 25 }
ドキュメントを削除:
> db.student.deleteOne({name:"李四"});
{ "acknowledged" : true, "deletedCount" : 1 }
> db.student.find()
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "老王子", "age" : 98 }
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "張三", "age" : 20 }
コマンドは非常に多く、さらに多くのコマンドについては公式ドキュメント:shell コマンドおよび公式ドキュメント:CRUD 操作を参照してください。
Go 言語による mongoDB 操作#
ここでは公式のドライバパッケージを使用しますが、もちろんサードパーティのドライバパッケージ(mgo など)を使用することもできます。 mongoDB 公式版の Go ドライバは比較的遅く(2018 年 12 月 13 日)にリリースされました。
mongoDB Go ドライバパッケージのインストール#
go get github.com/mongodb/mongo-go-driver
Go コードで mongoDB に接続#
package main
import (
"context"
"fmt"
"log"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
// クライアント接続設定を設定
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
// MongoDBに接続
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
}
// 接続を確認
err = client.Ping(context.TODO(), nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("MongoDBに接続しました!")
}
MongoDB に接続した後、上記の q1mi データベース内の student データセットを処理できます:
// 操作するデータセットを指定
collection := client.Database("q1mi").Collection("student")
タスクが完了したら、以下のコマンドで MongoDB との接続を切断できます:
// 接続を切断
err = client.Disconnect(context.TODO())
if err != nil {
log.Fatal(err)
}
fmt.Println("MongoDBとの接続が閉じられました。")
接続プールモード#
import (
"context"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func ConnectToDB(uri, name string, timeout time.Duration, num uint64) (*mongo.Database, error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
o := options.Client().ApplyURI(uri)
o.SetMaxPoolSize(num)
client, err := mongo.Connect(ctx, o)
if err != nil {
return nil, err
}
return client.Database(name), nil
}
BSON#
MongoDB の JSON ドキュメントは、BSON(バイナリエンコードされた JSON)というバイナリ表現で保存されます。他のデータベースが JSON データを単純な文字列や数字として保存するのとは異なり、BSON エンコーディングは JSON 表現を拡張し、int、long、date、浮動小数点数、decimal128 などの追加の型を含めます。これにより、アプリケーションはデータを信頼性高く処理、ソート、比較しやすくなります。
MongoDB の Go ドライバには、BSON データを表す 2 つの主要な型があります:D
とRaw
。
D
ファミリーは、ローカル Go 型を使用して BSON オブジェクトを簡潔に構築するために使用されます。これは、MongoDB に渡されるコマンドを構築する際に特に便利です。D
ファミリーには 4 つのタイプがあります:
- D:BSON ドキュメント。このタイプは順序が重要な場合に使用する必要があります。例えば MongoDB コマンド。
- M:順序のないマップ。D と同じですが、順序を保持しません。
- A:BSON 配列。
- E:D 内の 1 つの要素。
BSON を使用するには、以下のパッケージをインポートする必要があります:
import "go.mongodb.org/mongo-driver/bson"
以下は、D
型を使用して構築されたフィルタードキュメントの例で、name フィールドが「張三」または「李四」と一致するドキュメントを検索するために使用できます:
bson.D{{
"name",
bson.D{{
"$in",
bson.A{"張三", "李四"},
}},
}}
Raw
型ファミリーは、バイトスライスを検証するために使用されます。原始型から単一の要素を取得するためにLookup()
を使用することもできます。BSON を別の型に逆シリアル化するオーバーヘッドを避けたい場合に非常に便利です。このチュートリアルでは、D
型のみを使用します。
CRUD#
現在、Go コード内でStudent
型を以下のように定義します:
type Student struct {
Name string
Age int
}
次に、いくつかのStudent
型の値を作成し、データベースに挿入する準備をします:
s1 := Student{"小紅", 12}
s2 := Student{"小蘭", 10}
s3 := Student{"小黄", 11}
ドキュメントを挿入#
collection.InsertOne()
メソッドを使用して 1 つのドキュメントレコードを挿入:
insertResult, err := collection.InsertOne(context.TODO(), s1)
if err != nil {
log.Fatal(err)
}
fmt.Println("単一のドキュメントを挿入しました: ", insertResult.InsertedID)
collection.InsertMany()
メソッドを使用して複数のドキュメントレコードを挿入:
students := []interface{}{s2, s3}
insertManyResult, err := collection.InsertMany(context.TODO(), students)
if err != nil {
log.Fatal(err)
}
fmt.Println("複数のドキュメントを挿入しました: ", insertManyResult.InsertedIDs)
ドキュメントを更新#
updateone()
メソッドを使用して単一のドキュメントを更新できます。データベース内のドキュメントに一致するフィルタードキュメントが必要で、更新操作を記述する更新ドキュメントが必要です。フィルタードキュメントと更新ドキュメントを構築するためにbson.D
型を使用できます:
filter := bson.D{{"name", "小蘭"}}
update := bson.D{
{"$inc", bson.D{
{"age", 1},
}},
}
次に、以下の文を使用して小蘭を見つけ、1 歳を加えます:
updateResult, err := collection.UpdateOne(context.TODO(), filter, update)
if err != nil {
log.Fatal(err)
}
fmt.Printf("一致したドキュメント %v 件、更新されたドキュメント %v 件。\n", updateResult.MatchedCount, updateResult.ModifiedCount)
ドキュメントを検索#
ドキュメントを見つけるには、フィルタードキュメントと結果をデコードするためのポインタが必要です。単一のドキュメントを見つけるには、collection.FindOne()
を使用します。このメソッドは、値にデコードできる結果を返します。
上記で定義したフィルターを使用して、名前が「小蘭」のドキュメントを検索します。
// クエリ結果を受け取るためのStudent変数を作成
var result Student
err = collection.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
log.Fatal(err)
}
fmt.Printf("単一のドキュメントを見つけました: %+v\n", result)
複数のドキュメントを見つけるには、collection.Find()
を使用します。このメソッドはカーソルを返します。カーソルはドキュメントのストリームを提供し、1 つずつイテレートしてデコードできます。カーソルが使い果たされたら、カーソルを閉じる必要があります。以下の例では、options
パッケージを使用して、2 つのドキュメントのみを返すように制限を設定します。
// 複数をクエリ
// Find()にオプションを渡す
findOptions := options.Find()
findOptions.SetLimit(2)
// クエリ結果を格納するスライスを定義
var results []*Student
// bson.D{{}}をフィルターとして使用してすべてのドキュメントに一致させる
cur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions)
if err != nil {
log.Fatal(err)
}
// 複数のドキュメントを見つけてカーソルを返す
// カーソルをイテレートして1つずつドキュメントをデコード
for cur.Next(context.TODO()) {
// 値を作成し、単一のドキュメントをその値にデコード
var elem Student
err := cur.Decode(&elem)
if err != nil {
log.Fatal(err)
}
results = append(results, &elem)
}
if err := cur.Err(); err != nil {
log.Fatal(err)
}
// 完了後にカーソルを閉じる
cur.Close(context.TODO())
fmt.Printf("複数のドキュメントを見つけました(ポインタの配列): %#v\n", results)
ドキュメントを削除#
最後に、collection.DeleteOne()
またはcollection.DeleteMany()
を使用してドキュメントを削除できます。フィルター引数としてbson.D{{}}
を渡すと、データセット内のすべてのドキュメントに一致します。また、collection.drop()
を使用して、データセット全体を削除することもできます。
// 名前が小黄のドキュメントを削除
deleteResult1, err := collection.DeleteOne(context.TODO(), bson.D{{"name","小黄"}})
if err != nil {
log.Fatal(err)
}
fmt.Printf("トレーナーコレクション内のドキュメント %v 件を削除しました\n", deleteResult1.DeletedCount)
// すべてを削除
deleteResult2, err := collection.DeleteMany(context.TODO(), bson.D{{}})
if err != nil {
log.Fatal(err)
}
fmt.Printf("トレーナーコレクション内のドキュメント %v 件を削除しました\n", deleteResult2.DeletedCount)
その他のメソッドについては、公式ドキュメントを参照してください。
参考リンク#
https://docs.mongodb.com/manual/mongo/
https://www.mongodb.com/blog/post/mongodb-go-driver-tutorial