使用 Golang 为 MongoDB 构建类似 GORM 的 ORM

介绍

对象关系映射 (ORM) 是一种编程技术,可简化面向对象语言和关系数据库管理系统 (RDBMS) 之间的交互。 GORM 是一个流行的 Golang ORM 库,支持 MySQL、PostgreSQL 和 SQLite 等 RDBMS。 在本文中,我们将探索为 MongoDB(一种 NoSQL 数据库)构建类似 GORM 的 ORM,以使用 Golang 简化与 MongoDB 的交互。 我们将该系统称为“MONGORM”。

由于 MongoDB 以基于文档的格式存储数据,因此我们案例中的映射过程将是对象文档映射 (ODM)。 让我们深入创建 MONGORM,这是一个基于 Golang 的 MongoDB ORM。

设置和依赖关系

要开始构建 MONGORM,您需要安装并设置 Golang。 为此,您可以遵循官方 Golang 安装指南 ( https://golang.org/doc/install )。

接下来,您需要安装 MongoDB Go 驱动程序。 您可以使用以下命令来执行此操作:

go get go.mongodb.org/mongo-driver

建立连接

首先,我们创建一个函数来建立与 MongoDB 实例的连接。 创建一个名为 mongorm.go 的新 Go 文件,并添加以下代码:

package mongorm

import (
	"context"
	"fmt"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"log"
)

func Connect(uri string) (*mongo.Client, error) {
	clientOptions := options.Client().ApplyURI(uri)
	client, err := mongo.Connect(context.Background(), clientOptions)

	if err != nil {
		log.Fatal(err)
	}

	err = client.Ping(context.Background(), nil)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Successfully connected to MongoDB")
	return client, nil
}

定义模型

创建一个名为 model.go 的新 Go 文件,并定义将嵌入到所有其他模型中的基本模型结构。 该结构将包括 ID 字段和时间戳字段。

package mongorm

import (
	"go.mongodb.org/mongo-driver/bson/primitive"
	"time"
)

type Model struct {
	ID        primitive.ObjectID `bson:"_id,omitempty"`
	CreatedAt time.Time          `bson:"created_at"`
	UpdatedAt time.Time          `bson:"updated_at"`
}

CRUD增删改查操作

接下来,我们将在 mongorm.go 中实现所有模型都会使用的基本 CRUD 操作。 这些操作包括创建、读取、更新和删除。

func (m *Model) Create(ctx context.Context, db *mongo.Database, collectionName string, model interface{}) error {
	collection := db.Collection(collectionName)

	m.CreatedAt = time.Now()
	m.UpdatedAt = time.Now()

	res, err := collection.InsertOne(ctx, model)
	if err != nil {
		return err
	}

	m.ID = res.InsertedID.(primitive.ObjectID)
	return nil
}

func (m *Model) Read(ctx context.Context, db *mongo.Database, collectionName string, filter interface{}, result interface{}) error {
	collection := db.Collection(collectionName)

	err := collection.FindOne(ctx, filter).Decode(result)
	if err != nil {
		return err
	}

	return nil
}

func (m *Model) Update(ctx context.Context, db *mongo.Database, collectionName string, filter interface{}, update interface{}) error {
	collection := db.Collection(collectionName)

	m.UpdatedAt = time.Now()

	_, err := collection.UpdateOne(ctx, filter, update)
	if err != nil {
		return err
	}

	return nil
}

func (m *Model) Delete(ctx context.Context, db *mongo.Database, collectionName string, filter interface{}) error {
	collection := db.Collection(collectionName)
	_, err := collection.DeleteOne(ctx, filter)
	if err != nil {
		return err
	}

	return nil
}

使用示例

让我们创建一个简单的例子来演示 MONGORM 的用法。 假设我们有一个具有以下结构的“User”模型:

package main

import "github.com/yourusername/mongorm"

type User struct {
	mongorm.Model
	FirstName string `bson:"first_name"`
	LastName  string `bson:"last_name"`
	Email     string `bson:"email"`
}

现在,让我们使用 MONGORM 和 User 模型执行基本的 CRUD 操作:

package main

import (
	"context"
	"fmt"
	"github.com/yourusername/mongorm"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

func main() {
	// Replace the connection string with your own
	client, err := mongorm.Connect("mongodb://localhost:27017")
	if err != nil {
		panic(err)
	}

	db := client.Database("test_db")

	// Create a new user
	user := User{
		FirstName: "John",
		LastName:  "Doe",
		Email:     "[email protected]",
	}
	err = user.Create(context.Background(), db, "users", &user)
	if err != nil {
		panic(err)
	}
	fmt.Printf("User created: %v
", user)

	// Read a user by ID
	var readUser User
	err = readUser.Read(context.Background(), db, "users", bson.M{"_id": user.ID}, &readUser)
	if err != nil {
		panic(err)
	}
	fmt.Printf("User read: %v
", readUser)

	// Update a user's email
	update := bson.M{"$set": bson.M{"email": "[email protected]", "updated_at": primitive.NewDateTimeFromTime(user.UpdatedAt)}}
	err = user.Update(context.Background(), db, "users", bson.M{"_id": user.ID}, update)
	if err != nil {
		panic(err)
	}
	fmt.Printf("User updated: %v
", user)

	// Delete a user by ID
	err = user.Delete(context.Background(), db, "users", bson.M{"_id": user.ID})
	if err != nil {
		panic(err)
	}
	fmt.Println("User deleted")
}

此示例演示如何使用 MONGORM 使用 Golang 结构体创建、读取、更新和删除 MongoDB 集合中的文档。 您可以扩展 MONGORM 以支持更高级的功能,例如查询构建、关联和事务等。

结论

在本文中,我们探索了使用 Golang 为 MongoDB 构建一个类似 GORM 的 ORM,称为 MONGORM。 MONGORM 通过提供简洁、面向对象的方法简化了与 MongoDB 的交互。 虽然此处提供的示例涵盖了基本的 CRUD 操作,但您可以根据项目的要求进一步扩展 MONGORM 以支持更高级的功能。