статья:Пожалуйста, тестировщики, сообщите об этом, если обнаружите ошибку. Комментарий: Эта статья ориентирована на практичность и ясность. С точки зрения разработки она предоставляет тестировщикам подробные рекомендации по стандартизации сообщений об ошибках. Она направлена на снижение затрат на связь и повышение эффективности. Это практическое руководство для решения практических задач.
в использовании Go
языковая манипуляция MongoDB
час,Go
Предпочтительные библиотеки разработчиков обычно создаются MongoDB
Запущено официальной командой mongo-go-driver
。Эта библиотекада Предназначен для Go
Создано разработчиками языка для поддержки MongoDB
основные функции и с последней версией MongoDB
совместимый. проходить mongo-go-driver
,Go
Разработчики могут легко подключаться к базе данных и выполнять операции запроса, вставки, обновления и удаления коллекций.
хотя mongo-go-driver
Эта функция мощная, но за счет дальнейшей инкапсуляции эффективность разработки может быть значительно повышена в реальной разработке, особенно за счет уменьшения избыточности кода и улучшения читаемости в сложных сценариях. После инкапсуляции можно эффективно решить следующие распространенные проблемы:
BSON
структура данных. простой формат BSON
Данные легче записывать,Но в условиях сложной и многослойной вложенностидокументчас,Отнимает не только время,Также легко совершать ошибки. Даже небольшая оплошность,Это также может привести к отклонению результатов от ожиданий.,Увеличить уменьшает сложность отладки.BSON
Документация для определения различных этапов конвейера усложняет процесс.Поэтому я разработал go mongox
Библиотека оптимизирована для этих сценариев с использованием Go
Общие функции языка связывают структуры и вводят модульность. Creator
、Updater
、Deleter
、Finder
и Aggregator
и другие функции,Упростить вставку, возобновить, удалить, запрос иполимеризациядействовать соответственно. также,go mongox
Также предоставляется инструмент «Строить» для запросов и заявлений о возобновлении полимеризации.,к Уменьшить избыточность кода,Повышение эффективности разработки,Помогите разработчикам больше сосредоточиться на бизнеселогикареализация。
В этой статье будет подробно проанализирован go mongox
Идеи дизайна и практический опыт библиотек с открытым исходным кодом.
Вы готовы? Возьмите чашку любимого кофе или чая и узнайте, прочитав эту статью.
Адрес склада:https://github.com/chenmingyong0423/go-mongox чиновникдокумент:https://go-mongox.dev
go mongox
это библиотека на основе дженериков, которая расширяет MongoDB
официальные рамки. Посредством общей технологии он реализует структуру и MongoDB
собиратьобязательность,направлена на предоставлениебезопасность типаиупрощенные данныедействовать。go mongox
Также представлена цепная звонок, делает работу документа более плавной и обеспечивает богатые BSON
Строить ивстроенный функционал, упрощенный BSON
Построение данных。также,Он также имеет различные функции крючка.,Обеспечьте гибкость для пользовательской логики до и после работы базы данных.,Улучшенная масштабируемость и удобство обслуживания приложений.
MongoDB
собиратьCRUD
действоватьModel
Структура,автоматизациявозобновитьпо умолчанию field
ПолеBSON
Построение данныхtag
проверятьHooks
Чтобы совместить конструкцию с MongoDB
изсобирать Связывать,mongox
определяет общий Collection
Структура. через общие параметры T any
,это обеспечиваетбезопасность типаиз MongoDB
установить операции с сохранением оригинала *mongo.Collection
посещать.
type Collection[T any] struct {
collection *mongo.Collection
}
func (c *Collection[T]) Collection() *mongo.Collection {
return c.collection
}
func NewCollection[T any](collection *mongo.Collection) *Collection[T] {
return &Collection[T]{collection: collection}
}
Конструктивные особенности и преимущества
Collection[T]
Может напрямую работать с различными типами моделей данных. T
,Избегает утверждений и преобразований типов в традиционных методах.,Улучшена безопасность и читаемость кода.CRUD
Этот метод необходимо реализовать только один раз, чтобы адаптироваться ко всем типам моделей данных. Возможность повторного использования значительно снижает затраты на разработку и обслуживание.Collection()
метод позволяет пользователям напрямую получить доступ к базовому *mongo.Collection
,Оригинальная функциональность сохранена,совместимыйсложныйиз MongoDB
действоватьнуждаться。mongox
встроенныйпять независимыхиз Оператортип:Finder
、Creator
、Updater
、Deleter
и Aggregator
,Ответственность за каждогособиратьиз Находить、создавать、возобновлять、удалить и полимеризация действовать. Эти экземпляры операторов передаются Collection[T]
Предоставляются объекты, и каждый оператор фокусируется на определенной операции сбора.
func (c *Collection[T]) Finder() *finder.Finder[T] {
return finder.NewFinder[T](c.collection)
}
func (c *Collection[T]) Creator() *creator.Creator[T] {
return creator.NewCreator[T](c.collection)
}
func (c *Collection[T]) Updater() *updater.Updater[T] {
return updater.NewUpdater[T](c.collection)
}
func (c *Collection[T]) Deleter() *deleter.Deleter[T] {
return deleter.NewDeleter[T](c.collection)
}
func (c *Collection[T]) Aggregator() *aggregator.Aggregator[T] {
return aggregator.NewAggregator[T](c.collection)
}
// Опустить подробный код
type Finder[T any] struct {}
type Creator[T any] struct {}
type Updater[T any] struct {}
type Deleter[T any] struct {}
type Aggregator[T any] struct {}
Конструктивные особенности и преимущества:
SRP
)。проходить Различные подразделенияиз Оператормодуль,Уменьшает связь между функциями.Updater
тип функции. Новые функциональные модули не повлияют на стабильность других модулей.user, err := userColl.Finder().
Filter(query.Id("60e96214a21b1b0001c3d69e")).
FindOne(context.Background())
insertOneResult, err := userColl.Creator().
InsertOne(context.Background(), &User{Name: "Mingyong Chen", Age: 18})
updateResult, err := userColl.Updater().
Filter(query.Id("60e96214a21b1b0001c3d69e")).
Updates(update.Set("name", "Mingyong Chen")).
UpdateOne(context.Background())
deleteResult, err := userColl.Deleter().
Filter(query.Id("60e96214a21b1b0001c3d69e")).
DeleteOne(context.Background())
// Игнорировать возраст, искать только по имени
users, err := userColl.Aggregator().
Pipeline(aggregation.NewStageBuilder().Project(bsonx.M("age", 0)).Build()).
Aggregate(context.Background())
в дизайнеподдерживатьцепной При звонке Оператор Структура необходимо уточнить обязанности Структура и параметры, которые необходимо передать. Операторподдержкицепной Суть звонка Пошаговое выстраивание параметров, необходимых для работы,Наконец, когда вызывается метод выполнения, параметры передаются полностью и выполняется операция.
к Updater
Например, он фокусируется на возобновлять в этой сцене действовать цепной Цель звонка — непрерывный вызов методов для постепенного выполнения следующих задач:
filter
):Укажите потребностивозобновлятьиздокументобъем。updates
):Объясните, как изменить Документальный фильм Поле。к Внизда Updater
Реализация:
type Updater[T any] struct {
collection *mongo.Collection
filter any
updates any
}
func (u *Updater[T]) Filter(filter any) *Updater[T] {
u.filter = filter
return u
}
func (u *Updater[T]) Updates(updates any) *Updater[T] {
u.updates = updates
return u
}
func (u *Updater[T]) UpdateOne(ctx context.Context, opts ...options.Lister[options.UpdateOptions]) (*mongo.UpdateResult, error) {
// Игнорировать подробный код
}
func (u *Updater[T]) UpdateMany(ctx context.Context, opts ...options.Lister[options.UpdateOptions]) (*mongo.UpdateResult, error) {
// Игнорировать подробный код
}
func (u *Updater[T]) Upsert(ctx context.Context, opts ...options.Lister[options.UpdateOptions]) (*mongo.UpdateResult, error) {
// Игнорировать подробный код
}
Конструктивные особенности и преимущества:
Filter
Строить Условия запроса,Updates
Строитьвозобновлятьсодержание),проведениецепного звонка поэтапная подготовка параметров для сложного действия,Использование упрощенного метода.updateResult, err := userColl.Updater().
Filter(query.Id("60e96214a21b1b0001c3d69e")).
Updates(update.Set("name", "Mingyong Chen")).
UpdateOne(context.Background())
Updater
Увеличивать Hook
или функция журнала.Для других операторов, таких как Creator
и Finder
и т. д., концепция дизайна также аналогична.
mongox
Библиотека предоставляет мощные BSON
Функция построения данных помогает разработчикам упростить и MongoDB
Комплекс при общении BSON
Построение данных。для Решение типичных проблем в разработкеиз Строить Сложный запрос、возобновлятьсодержаниекиполимеризациятрубопроводчасизутомительные вопросы,mongox
Разделите функции на следующие категории:
query
СумкаBSON
данные.$and
、$or
)、объем Запрос($gt
、$lt
)ждать Сложный запрос。update
модульBSON
данные, например $set
、$inc
ждать.aggregation
модульMongoDB
изполимеризациятрубопровод(pipeline
)。$match
、$group
、$project
ждать.bsonx
модульBSON
Данные, охватывающие общие потребности за пределами запросов, возобновляютполимеризацию.дляподдерживать Простой Строитьисложный Строить,query
Сумка предлагает два режима Строить: Прямая. конструкция функцииистроитель строить。
Для поддержки простых операторов запроса и сложных операторов запроса для Строить,query
Сумкапредоставил Два вида гибкостииз Строитьмодель:Прямая конструкция функции и строитель строить。этотдва путиизобъединяет контент из быстрых Строитьприезжатьсложныйлогика Выражатьиз Различныйнуждаться。
Обработка предоставляет простые функции, которые разработчики могут быстро создать одним действием. BSON
Условия запроса. Этот подход подходит для простых запросов, не требующих комбинационной логики.
func Eq(key string, value any) bson.D {
return bson.D{bson.E{Key: key, Value: bson.D{{Key: "$eq", Value: value}}}}
}
func Lt(key string, value any) bson.D {
return bson.D{bson.E{Key: key, Value: bson.D{{Key: "$lt", Value: value}}}}
}
// Игнорировать другие реализации функций
Пример использования:
// {
// "name": "Чен Минён"
// }
eq := query.Eq("name", "Чен Минён")
для Сложный запрослогикаиз Строить,mongox
Обеспечивает мощный Builder
Строитьустройство,проходитьцепной звонок путь шаг за шагом Строить комплекс BSON
данные.
func NewBuilder() *Builder {
query := &Builder{
data: bson.D{},
err: make([]error, 0),
}
query.comparisonQueryBuilder = comparisonQueryBuilder{parent: query}
query.logicalQueryBuilder = logicalQueryBuilder{parent: query}
query.elementQueryBuilder = elementQueryBuilder{parent: query}
query.arrayQueryBuilder = arrayQueryBuilder{parent: query}
query.evaluationQueryBuilder = evaluationQueryBuilder{parent: query}
query.projectionQueryBuilder = projectionQueryBuilder{parent: query}
return query
}
type Builder struct {
data bson.D
comparisonQueryBuilder
logicalQueryBuilder
elementQueryBuilder
arrayQueryBuilder
evaluationQueryBuilder
projectionQueryBuilder
}
func (b *Builder) Build() bson.D {
return b.data
}
По своей сути построители создаются с помощью построителей комбинаторов, таких как comparisonQueryBuilder
)Реализация другаядействоватьсимволизлогика。каждыйребенок Строитьустройствопредоставить свой эксклюзивныйиз Цепь方法,Builder
Полный набор функций формируется путем объединения этих методов.
Реализация суббилдера (пример)
type comparisonQueryBuilder struct {
parent *Builder
}
func (b *comparisonQueryBuilder) Eq(key string, value any) *Builder {
e := bson.E{Key: EqOp, Value: value}
if !b.parent.tryMergeValue(key, e) {
b.parent.data = append(b.parent.data, bson.E{Key: key, Value: bson.D{e}})
}
return b.parent
}
func (b *comparisonQueryBuilder) Gt(key string, value any) *Builder {
e := bson.E{Key: GtOp, Value: value}
if !b.parent.tryMergeValue(key, e) {
b.parent.data = append(b.parent.data, bson.E{Key: key, Value: bson.D{e}})
}
return b.parent
}
func (b *comparisonQueryBuilder) Lt(key string, value any) *Builder {
e := bson.E{Key: LtOp, Value: value}
if !b.parent.tryMergeValue(key, e) {
b.parent.data = append(b.parent.data, bson.E{Key: key, Value: bson.D{e}})
}
return b.parent
}
Основная функция строителя:
Builder
Предоставляет методы для пошагового построения условий запроса.Пример использования:
// {
// "age": {
// "$gt": {
// "$numberInt": "18"
// },
// "$lt": {
// "$numberInt": "30"
// }
// }
// }
query.NewBuilder().Gt("age", 18).Lt("age", 30).Build()
Похоже на: query
Сумка,mongox
другие модули в (например. update
、aggregation
、bsonx
)Также принят аналогичныйиздизайнмодель,предоставил Прямая конструкция функцииистроитель построить два пути,поддерживатьцепной звоноккупрощатьсложныйлогикаиз Строить。ловить Вниз Я не буду их здесь представлять.。
Конструктивные особенности и преимущества
mongox
поддерживатьпрограммирование плагинов,Он обеспечивает гибкий способ вставки пользовательской логики до и после работы базы данных.,Тем самым повышается масштабируемость и удобство обслуживания приложения. Очень подходит для следующих сценариев:
_id
Поле значения исписывать время и возобновлять время.Callback
да mongox
программирование Ядро плагинов. Он содержит ряд свойств перехватчика (таких как beforeInsert
、afterInsert
и т. д.) Привязывайте пользовательскую логику к конкретным этапам операций сбора.
// Глобальный менеджер обратного звонка
var Callbacks = initializeCallbacks()
// инициализация Callback
func initializeCallbacks() *Callback {
return &Callback{
beforeInsert: make([]callbackHandler, 0),
afterInsert: make([]callbackHandler, 0),
beforeUpdate: make([]callbackHandler, 0),
afterUpdate: make([]callbackHandler, 0),
beforeDelete: make([]callbackHandler, 0),
afterDelete: make([]callbackHandler, 0),
beforeUpsert: make([]callbackHandler, 0),
afterUpsert: make([]callbackHandler, 0),
beforeFind: make([]callbackHandler, 0),
afterFind: make([]callbackHandler, 0),
}
}
type Callback struct {
beforeInsert []callbackHandler
afterInsert []callbackHandler
beforeUpdate []callbackHandler
afterUpdate []callbackHandler
beforeDelete []callbackHandler
afterDelete []callbackHandler
beforeUpsert []callbackHandler
afterUpsert []callbackHandler
beforeFind []callbackHandler
afterFind []callbackHandler
}
type callbackHandler struct {
name string
fn CbFn
}
type CbFn func(ctx context.Context, opCtx *operation.OpContext, opts ...any) error
// operation_type.go
type OpContext struct {
Col *mongo.Collection `opt:"-"`
Doc any
// filter also can be used as query
Filter any
Updates any
Replacement any
MongoOptions any
ModelHook any
}
func (c *Callback) Execute(ctx context.Context, opCtx *operation.OpContext, opType operation.OpType, opts ...any) error {
switch opType {
// Игнорировать детали реализации в соответствии с типом действия. opType Выполните соответствующую функцию обратного вызова.
}
return nil
}
before
и after
Два вида крючков.callbackHandler
:name
:钩ребенок函数изимя,Легко управлять и отлаживать.fn
:специфическийизфункция обратного вызова,Реализация настройкилогика。CbFn
функция обратного вызова:ctx
:начальство Внизискусство,Используется для управления жизненным циклом обратных вызовов.opCtx
:действоватьначальство Внизискусство,Сумка содержит параметры, связанные с работой базы данных.opts
:Можетвыбиратьпараметр,Используется для передачи дополнительной информации.Execute
Метод в соответствии с типом операции Находить соответствующий список крючков и в порядке Выполнить обратный вызов。OpContext
дафункция обратного вызоваизосновнойпараметр,Предоставляет подробную информацию о сборедействующих данных.,Чтобы разработчики могли гибко использовать функции обратного вызова.
type OpContext struct {
Col *mongo.Collection `opt:"-"` // MongoDB собирать Пример
Doc any // документ
Filter any // Условия запроса
Updates any // возобновлятьсодержание
Replacement any // Заменить контент
MongoOptions any // MongoDB Нативные варианты
ModelHook any // Используется для определения того, реализована ли привязка Структурада. Model Hook
}
Описание основного поля:
Col
:текущийдействоватьизсобирать Пример。Doc
:документ。Filter
:действоватьиз Условия запроса,нравиться Находить、возобновлятьилиудалитьчасиспользовать。Updates
:возобновлятьсодержание。Replacement
:заменятьдействоватьиздокументсодержание。MongoOptions
:передача MongoDB
Родной вариант активации.ModelHook
:и Связанные с модельюиз自定义начальство Внизискусство,Расширяемый для использования.// Зарегистрировать плагин
mongox.RegisterPlugin("after find", func(ctx context.Context, opCtx *operation.OpContext, opts ...any) error {
if user, ok := opCtx.Doc.(*User); ok {
fmt.Println(user)
}
if users, ok := opCtx.Doc.([]*User); ok {
fmt.Println(users)
}
return nil
},operation.OpTypeAfterFind)
// удалитьплагин
mongox.RemovePlugin("after find", operation.OpTypeAfterFind)
Execute
Метод к запускает зарегистрированный обратный вызов:err = callback.GetCallback().Execute(ctx, globalOpContext, opType)
if err != nil {
return
}
before
и after
Разработчики могут свободно комбинировать и расширять хуки.
Масштабируемость:
- Обратные вызовы хранятся в виде срезов, что позволяет динамически удалять или заменять функции-перехватчики.OpContext
Предоставляет комплексный контекст действий для легкой отладки и расширения.В этой статье подробно рассказывается go mongox
Открытый исходный Идеи дизайна и практический опыт библиотеки кодов охватывают несколько основных модулей Проектирование и реализация,Сумка Прилагаемое содержимое:
Collection[T]
Проектирование и реализация:безопасность типаизсобирать Инкапсуляция;CRUD
Оператор(нравиться Finder
、Creator
、Updater
、Deleter
、Aggregator
):модульизменятьиз增删改查дизайн;BSON
Пакет построения данных(query
、update
、aggregate
):Эффективный Строить Запрос、возобновлятьиполимеризация Связанныйиз BSON
данные;Хотя разработка функции, аналогичной go mongox
из В библиотеке нетсложный,Но как тщательно спроектировать, чтобы добиться превосходной масштабируемости, простоты использования и возможности повторного использования?,Это вопрос, над которым разработчикам следует глубоко задуматься. Я надеюсь, что эта статья предоставит вам практические идеи и опыт.
Давайте присоединимся и внесем свой вклад, давайте
go mongox
Практичнее! Если присоединишься, иди mongox Станет Практичнее!
Привет, я да Чен Минён, разработчик, который любит технологии и готов ими делиться, а также да Открытый исходный любитель кодов.
Путь к успеху не переполнен. Вы заинтересованы в поиске партнера?
Следуйте за мной, добавляйте меня в друзья, учитесь и совершенствуйтесь вместе!