Введение

Объектно-реляционное отображение (ORM) — это метод программирования, который упрощает взаимодействие между объектно-ориентированным языком и системой управления реляционными базами данных (RDBMS). GORM — это популярная библиотека ORM для Golang, которая поддерживает такие СУБД, как MySQL, PostgreSQL и SQLite. В этой статье мы рассмотрим создание ORM-подобного GORM для MongoDB, базы данных NoSQL, чтобы упростить взаимодействие с MongoDB с помощью Golang. Мы будем называть эту систему «MONGORM».

Поскольку MongoDB хранит данные в формате, основанном на документах, процесс сопоставления в нашем случае будет представлять собой сопоставление объектов и документов (ODM). Давайте углубимся в создание MONGORM, ORM на основе Golang для MongoDB.

Настройка и зависимости

Чтобы начать сборку MONGORM, вам необходимо установить и настроить Golang. Для этого вы можете воспользоваться официальным руководством по установке Golang (https://golang.org/doc/install).

Далее вам нужно установить драйвер MongoDB Go. Вы можете сделать это с помощью следующей команды:

go get go.mongodb.org/mongo-driver

Установление соединения

Во-первых, давайте создадим функцию для установления соединения с экземпляром MongoDB. Создайте новый файл Go с именем mongorm.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
}

Определение моделей

Создайте новый файл Go с именем model.go и определите структуру базовой модели, которая будет встроена во все остальные модели. Эта структура будет включать поле идентификатора и поля метки времени.

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-операции

Далее мы реализуем базовые операции CRUD в mongorm.go, которые будут использоваться всеми моделями. Эти операции включают создание, чтение, обновление и удаление.

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"`
}

Теперь давайте выполним основные операции CRUD, используя MONGORM с моделью User:

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\n", 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\n", 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\n", 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 для создания, чтения, обновления и удаления документов в коллекции MongoDB с использованием структуры Golang. Вы можете расширить MONGORM для поддержки более продвинутых функций, таких как построение запросов, ассоциации и транзакции, среди прочего.

Заключение

В этой статье мы рассмотрели создание ORM-подобного GORM для MongoDB под названием MONGORM с использованием Golang. MONGORM упрощает взаимодействие с MongoDB, обеспечивая чистый объектно-ориентированный подход. Хотя приведенный здесь пример охватывает основные операции CRUD, вы можете дополнительно расширить MONGORM для поддержки более продвинутых функций в соответствии с требованиями вашего проекта.