mongo docker版
This commit is contained in:
parent
3ee707e60c
commit
13cd706505
|
|
@ -0,0 +1,109 @@
|
||||||
|
package mongo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mongo_uri string
|
||||||
|
mongo_database string
|
||||||
|
mongo_username string
|
||||||
|
mongo_password string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
mongo_uri = os.Getenv("MONGO_URI")
|
||||||
|
if mongo_uri == "" {
|
||||||
|
mongo_uri = "mongodb://localhost:27017"
|
||||||
|
}
|
||||||
|
mongo_database = os.Getenv("MONGO_DB")
|
||||||
|
if mongo_database == "" {
|
||||||
|
mongo_database = "admin"
|
||||||
|
}
|
||||||
|
mongo_username = os.Getenv("MONGO_USERNAME")
|
||||||
|
mongo_password = os.Getenv("MONGO_PASSWORD")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新连接获取
|
||||||
|
func newConnect() (*mongo.Client, error) {
|
||||||
|
clientOpts := options.Client().ApplyURI(mongo_uri).SetConnectTimeout(3 * time.Second)
|
||||||
|
|
||||||
|
if mongo_username != "" && mongo_password != "" {
|
||||||
|
clientOpts = clientOpts.SetAuth(options.Credential{
|
||||||
|
AuthMechanism: "SCRAM-SHA-256",
|
||||||
|
AuthSource: "admin",
|
||||||
|
Username: mongo_username,
|
||||||
|
Password: mongo_password,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
return mongo.Connect(ctx, clientOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDB(client *mongo.Client, dbname string) (*mongo.Database, error) {
|
||||||
|
db := dbname
|
||||||
|
if db == "" {
|
||||||
|
db = mongo_database
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.Database(db), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCollection(client *mongo.Client, dbname, colname string) (*mongo.Collection, error) {
|
||||||
|
db, err := newDB(client, dbname)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return db.Collection(colname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取默认集合,即数据库名已指定的库
|
||||||
|
func newDefaultCollection(client *mongo.Client, colname string) (*mongo.Collection, error) {
|
||||||
|
db, err := newDB(client, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return db.Collection(colname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ping() error {
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
defer client.Disconnect(ctx)
|
||||||
|
return client.Ping(ctx, readpref.Primary())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collection 获取集合
|
||||||
|
func Collection(client *mongo.Client, cname string) (*mongo.Collection, error) {
|
||||||
|
collection := client.Database(mongo_database).Collection(cname)
|
||||||
|
return collection, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollectionMulti 支持多数据库直接获取collection
|
||||||
|
func CollectionMulti(client *mongo.Client, cname string) (*mongo.Collection, error) {
|
||||||
|
name := strings.Split(cname, ".")
|
||||||
|
if len(name) != 2 {
|
||||||
|
return nil, errors.New("collection名称不正确,请使用[database.collection]方式使用")
|
||||||
|
}
|
||||||
|
if name[0] == "" || name[1] == "" {
|
||||||
|
return nil, errors.New("名称不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
collection := client.Database(name[0]).Collection(name[1])
|
||||||
|
return collection, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,270 @@
|
||||||
|
package mongo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
mongo_uri = "mongodb://192.168.0.254:27017"
|
||||||
|
mongo_database = "sample"
|
||||||
|
mongo_username = "aaa"
|
||||||
|
mongo_password = "bbb123"
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPing(t *testing.T) {
|
||||||
|
if err := ping(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Student struct {
|
||||||
|
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"` //确保在 BSON 编码/解码时,当 _id 为空时不会将其包含在文档中。在插入文档时,可以不设置 ID 字段,MongoDB 驱动会自动为其生成一个唯一的 ObjectID。
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Sex string `json:"sex,omitempty"`
|
||||||
|
CourseID int `bson:"courseid,omitempty" json:"course_id,omitempty"`
|
||||||
|
StudentID int `json:"student_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInsert(t *testing.T) {
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer client.Disconnect(context.Background())
|
||||||
|
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
collection, err := newCollection(client, "", "student")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
n := fmt.Sprintf("张小凡%d", i)
|
||||||
|
ret, err := collection.InsertOne(context.Background(), &Student{Name: n, Sex: "女", StudentID: i, CourseID: i % 10})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(i, ret)
|
||||||
|
fmt.Println(ret.InsertedID.(primitive.ObjectID).Hex())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInsertCourse(t *testing.T) {
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer client.Disconnect(context.Background())
|
||||||
|
|
||||||
|
for i := 2; i < 10; i++ {
|
||||||
|
collection, err := newCollection(client, "", "course")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
n := fmt.Sprintf("sports%d", i)
|
||||||
|
ret, err := collection.InsertOne(context.Background(), &Course{ID: i, Name: n, Title: "sports"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(i, ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer client.Disconnect(context.Background())
|
||||||
|
col, err := newCollection(client, "", "student")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := col.FindOneAndDelete(context.Background(), bson.D{{"name", "张惠"}}).Err(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ret, err := col.DeleteOne(context.Background(), bson.D{{"name", "张惠"}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(ret)
|
||||||
|
ret, err = col.DeleteMany(context.Background(), bson.D{{"name", "张惠"}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSingleResult(t *testing.T) {
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
defer client.Disconnect(ctx)
|
||||||
|
col, err := Collection(client, "student")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var result Student
|
||||||
|
// if err := col.FindOne(ctx, bson.D{{"name", "张惠"}}).Decode(&result); err != nil {
|
||||||
|
if err := col.FindOne(ctx, bson.M{"name": "张惠0"}).Decode(&result); err != nil {
|
||||||
|
if err != mongo.ErrNoDocuments {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindAll(t *testing.T) {
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
defer client.Disconnect(ctx)
|
||||||
|
col, err := newCollection(client, "", "student")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cur, err := col.Find(ctx, bson.D{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer cur.Close(ctx)
|
||||||
|
for cur.Next(ctx) {
|
||||||
|
var result Student
|
||||||
|
if err := cur.Decode(&result); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(result, result.ID.String(), result.ID.Timestamp(), result.ID.Timestamp().Local())
|
||||||
|
}
|
||||||
|
if err := cur.Err(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFind(t *testing.T) {
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
defer client.Disconnect(ctx)
|
||||||
|
col, err := newDefaultCollection(client, "student")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cur, err := col.Find(ctx, bson.M{"name": "张小凡1"}) //注意这里的格式$ne不相等,$gt大于,$gte大于等于,$in in,$nin no in ,$exists是否包含这个键...
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer cur.Close(ctx)
|
||||||
|
for cur.Next(ctx) {
|
||||||
|
var result Student
|
||||||
|
if err := cur.Decode(&result); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(result, result.ID.String(), result.ID.Timestamp(), result.ID.Timestamp().Local())
|
||||||
|
}
|
||||||
|
if err := cur.Err(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPage(t *testing.T) {
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
defer client.Disconnect(ctx)
|
||||||
|
col, err := newDefaultCollection(client, "student")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cur, err := col.Find(ctx, bson.M{}, options.Find().SetSkip(1000).SetLimit(1000))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer cur.Close(ctx)
|
||||||
|
for cur.Next(ctx) {
|
||||||
|
var result Student
|
||||||
|
if err := cur.Decode(&result); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(result, result.ID.String(), result.ID.Timestamp(), result.ID.Timestamp().Local())
|
||||||
|
}
|
||||||
|
if err := cur.Err(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Course struct {
|
||||||
|
ID int `bson:"_id,omitempty" json:"id,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关连表查询
|
||||||
|
func TestAggregate(t *testing.T) {
|
||||||
|
// 建立 MongoDB 连接
|
||||||
|
client, err := newConnect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer client.Disconnect(context.Background())
|
||||||
|
|
||||||
|
// 选择数据库和集合
|
||||||
|
studentsCollection, err := newDefaultCollection(client, "student")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行关联查询
|
||||||
|
pipeline := bson.A{
|
||||||
|
bson.D{
|
||||||
|
{"$match", bson.D{
|
||||||
|
{"name", "张小凡1"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
bson.D{
|
||||||
|
{"$lookup", bson.D{
|
||||||
|
{"from", "course"},
|
||||||
|
{"localField", "courseid"},
|
||||||
|
{"foreignField", "_id"},
|
||||||
|
{"as", "courses"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行聚合查询,结果OK
|
||||||
|
cursor, err := studentsCollection.Aggregate(context.Background(), pipeline)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer cursor.Close(context.Background())
|
||||||
|
|
||||||
|
// 解码查询结果
|
||||||
|
var result []bson.M
|
||||||
|
if err := cursor.All(context.Background(), &result); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印查询结果
|
||||||
|
fmt.Println("Result:")
|
||||||
|
for _, doc := range result {
|
||||||
|
fmt.Println(doc)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue