go-mongox: Generic Collection, Streamlined Document Operations, Efficient Build Bson, Plugin Programming

A Go Mongo package with streamlined document operations and efficient BSON data builder using generics.

What is go-mongox?

go-mongox is a generics-based library that extends the official MongoDB framework. Utilizing generic programming, it facilitates the binding of structs to MongoDB collections, aiming to provide type safety and streamlined data operations.

go-mongox introduces chainable calls for smoother document handling and offers a rich set of bson builders and built-in functions to simplify the build of bson data.

Moreover, it supports plugin-based programming and incorporates various hooks, offering flexibility for custom logic before and after database operations, thus enhancing the application's extensibility and maintainability.

Github: go-mongox

Contribute to go-mongox!

With your involvement, go-mongox will become even more powerful!

Feature Highlights

  • Generic MongoDB Collection
  • CRUD operations on documents
  • Aggregation operations
  • Built-in basic Model structure for automated updates of default field fields
  • Support for building bson data
  • Struct tags validation
  • Hooks
  • Plugin programming support

Installation

To install the go-mongox module in your Go application, execute the following command:

go get github.com/chenmingyong0423/go-mongox

Builders

go-mongox has designed various types of BSON builders and functions, providing robust support for developers constructing BSON data in different scenarios. Whether it's for data queries, updates, or complex aggregation operations, developers can find suitable builders or functions in specialized packages such as bsonx, query, update, and aggregation. These BSON builders and functions not only optimize the coding process but also significantly enhance development efficiency, making it simple and efficient to handle complex BSON data.

Query Statement Construction - query package

The query package provides convenient methods for building MongoDB query conditions. It includes a series of functions and builders designed to simplify the construction of query conditions. For complex query conditions, builders offer flexible building methods through chainable calls; for simple needs, functions are available for quick construction.

Simple Construction

For a single query condition, we directly use functions to build.

// bson.D{bson.E{Key:"_id", Value:"12345678"}}
/*
{
  "_id": "12345678"
}
*/
query.Id("12345678")

// bson.D{bson.E{Key:"name", Value:bson.D{bson.E{Key:"$in", Value:[]string{"Mingyong Chen", "chenmingyong"}}}}}
/*
{
  "name": {
    "$in": ["Mingyong Chen", "chenmingyong"]
  }
}
*/
query.In("name", "Mingyong Chen", "chenmingyong")

// bson.D{bson.E{Key:"age", Value:bson.D{bson.E{Key:"$gte", Value:18}}}}
/*
{
  "age": {
    "$gte": 18
  }
}
*/
query.Gte("age", 18)

// bson.D{bson.E{Key:"name", Value:bson.D{bson.E{Key:"$regex", Value:".*cmy.*"}, bson.E{Key:"$options", Value:"i"}}}}
/*
{
  "name": {
    "$regex": ".*cmy.*",
    "$options": "i"
  }
}
*/
query.RegexOptions("name", ".*cmy.*", "i")

The query package's functions optimize the coding process, enhancing development efficiency.

For more details, please visit the official documentation: query package | go-mongox.

Complex Construction

For more complex BSON data formats, we use builders for construction.

// bson.D{bson.E{Key:"age", Value:bson.D{bson.E{Key:"$gte", Value:18}, bson.E{Key:"$lte", Value:25}}}, bson.E{Key:"name", Value:bson.D{bson.E{Key:"$in", Value:[]interface {}{"Mingyong Chen", "chenmingyong"}}}}}
/*
{
  "age": {
    "$gte": 18,
    "$lte": 25
  },
  "name": {
    "$in": ["Mingyong Chen", "chenmingyong"]
  }
}
*/
query.BsonBuilder().Gte("age", 18).Lte("age", 25).In("name", "Mingyong Chen", "chenmingyong").Build()

// bson.D{bson.E{Key:"lastLogin", Value:bson.D{bson.E{Key:"$gte", Value:time.Date(2024, time.March, 0, 0, 0, 0, 189625000, time.Local)}}}, bson.E{Key:"$or", Value:[]interface {}{bson.D{bson.E{Key:"status", Value:bson.D{bson.E{Key:"$eq", Value:"active"}}}}, bson.D{bson.E{Key:"loginAttempts", Value:bson.D{bson.E{Key:"$gte", Value:5}}}}}}}
/*
{
  "lastLogin": {
    "$gte": "2024-03-08T00:00:00.189Z"
  },
  "$or": [
    {
      "status": {
        "$eq": "active"
      }
    },
    {
      "loginAttempts": {
        "$gte": 5
      }
    }
  ]
}
*/
query.BsonBuilder().Gte("lastLogin", time.Now().Add(-30*24*time.Hour)).Or(
    query.Eq("status", "active"),
    query.Gte("loginAttempts", 5),
).Build()

// bson.D{bson.E{Key:"name", Value:bson.D{bson.E{Key:"$eq", Value:"Mingyong Chen"}}}, bson.E{Key:"hobbies", Value:bson.D{bson.E{Key:"$elemMatch", Value:primie.D{bson.E{Key:"name", Value:bson.D{bson.E{Key:"$eq", Value:"coding"}}}, bson.E{Key:"level", Value:bson.D{bson.E{Key:"$gte", Value:5}}}}}}}}
/*
{
  "name": {
    "$eq": "Mingyong Chen"
  },
  "hobbies": {
    "$elemMatch": {
      "name": {
        "$eq": "coding"
      },
      "level": {
        "$gte": 5
      }
    }
  }
}
*/
query.BsonBuilder().
    Eq("name", "Mingyong Chen").
    ElemMatch("hobbies", query.BsonBuilder().Eq("name", "coding").Gte("level", 5).Build()).
    Build()

Through these examples, we can see the power of builders, which use a chainable call approach to construct complex query statements. This method makes the code clearer, easier to read, maintain, and extend.

For more details, please visit the official documentation: query package | go-mongox.

Document Update Construction - update package

The update package provides convenient methods for constructing MongoDB update documents. It includes a series of functions and builders designed to simplify the construction of update documents. For complex update documents, builders offer flexible building methods through chainable calls; for simple needs, functions are available for quick construction.

Simple Construction

For a single update document, we directly use functions to build.

// bson.D{bson.E{Key:"$set", Value:bson.D{bson.E{Key:"name", Value:"Mingyong Chen"}}}}
/*
{
  "$set": {
    "name": "Mingyong Chen"
  }
}
*/
update.Set("name", "Mingyong Chen")

// bson.D{bson.E{Key:"$inc", Value:bson.D{bson.E{Key:"money", Value:"100000"}}}}
/*
{
  "$inc": {
    "money": 100000
  }
}
*/
update.Inc("money", "100000")

// bson.D{bson.E{Key:"$push", Value:bson.D{bson.E{Key:"tags", Value:"golang"}}}}
/*
{
  "$push": {
    "tags": "golang"
  }
}
*/
update.Push("tags", "golang")

For more details, please visit the official documentation: update package | go-mongox.

Complex Construction

For more complex update documents, we use builders for construction.

// bson.D{bson.E{Key:"$set", Value:bson.D{bson.E{Key:"name", Value:"Mingyong Chen"}, bson.E{Key:"age", Value:18}}}}
/*{
  "$set": {
    "name": "Mingyong Chen",
    "age": 18
  }
}
*/
update.BsonBuilder().Set("name", "Mingyong Chen").Set("age", 18).Build()

// bson.D{bson.E{Key:"$set", Value:bson.D{bson.E{Key:"update_at", Value:time.Date(2024, time.April, 7, 3, 13, 23, 958924000, time.Local)}}}, bson.E{Key:"$inc", Value:bson.D{bson.E{Key:"view", Value:1}}}}
/*{
  "$set": {
    "update_at": "2024-04-07T00:00:00.958Z"
  },
  "$inc": {
    "view": 1
  }
}
*/
update.BsonBuilder().Set("update_at", time.Now()).Inc("view", 1).Build()

// bson.D{bson.E{Key:"$push", Value:bson.D{bson.E{Key:"comments", Value:"New Comment"}}}, bson.E{Key:"$inc", Value:bson.D{bson.E{Key:"commentCount", Value:}}}
/*
{
  "$push": {
    "comments": "New Comment"
  },
  "$inc": {
    "commentCount": 1
  }
}
*/
update.BsonBuilder().Push("comments", "New Comment").Inc("commentCount", 11).Build()

For more details, please visit the official documentation: update package | go-mongox.

Aggregation Pipeline Stages and Expression Construction - aggregation package

The aggregation package provides convenient methods to construct MongoDB aggregation pipelines (pipeline). It includes multiple functions and builders, simplifying the pipeline construction process. For complex scenarios, builders support chainable calls, making the construction process more flexible; for basic needs, functions can quickly complete the construction.

The aggregation package offers two types of builders:

  • aggregation.StageBuilder: For easily constructing various stages of the aggregation pipeline, such as $group, $match, etc. Create a new builder instance with aggregation.StageBsonBuilder(), then call the appropriate methods to build the stage.
  • aggregation.Builder: For constructing complex expressions used within pipeline stages, such as conditional logic, mathematical operations, etc. Create a new builder instance with aggregation.BsonBuilder(), then call the appropriate methods to build the expression.

Aggregation Pipeline Stages

The aggregation stage builder is used for easily constructing various stages of the aggregation pipeline, such as $group, $match, etc.

Create a new builder instance with aggregation.StageBsonBuilder(), then call the appropriate methods to build the stage.

type User struct {
    mongox.Model `bson:"inline"`
    Name         string `bson:"name"`
    Age          int    `bson:"age"`
}

// mongo.Pipeline{bson.D{bson.E{Key:"$group", Value:bson.D{bson.E{Key:"_id", Value:"$age"}, bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}, bson.E{Key:"names", Value:bson.D{bson.E{Key:"$push", Value:"$name"}}}}}}}
/*[
  {
    "$group": {
      "_id": "$age",
      "count": { "$sum": 1 },
      "names": { "$push": "$name" }
    }
  }
]
*/
aggregation.StageBsonBuilder().Group("$age",
    aggregation.BsonBuilder().Sum("count", 1).Push("names", "$name").Build()...,
).Build()

// mongo.Pipeline{bson.D{bson.E{Key:"$addFields", Value:bson.D{bson.E{Key:"isAdult", Value:bson.D{bson.E{Key:"$gte", Value:[]interface {}{"$age", 18}}}}}}}, bson.E{Key:"$replaceWith", Value:bson.D{bson.E{Key:"name", Value:"$name"}, bson.E{Key:"isAdult", Value:"$isAdult"}}}}}
/*
[
  {
    "$addFields": {
      "isAdult": {
        "$gte": ["$age", 18]
      }
    }
  },
  {
    "$replaceWith": {
      "name": "$name",
      "isAdult": "$isAdult"
    }
  }
]
*/
aggregation.StageBsonBuilder().
    AddFields(aggregation.Gte("isAdult", "$age", 18)).
    ReplaceWith(bsonx.NewD().Add("name", "$name").Add("isAdult", "$isAdult").Build()).Build()

// mongo.Pipeline{bson.D{bson.E{Key:"$bucket", Value:bson.D{bson.E{Key:"groupBy", Value:"$age"}, bson.E{Key:"boundaries", Value:[]interface {}{0, 19, 31, 46, +Inf}}, bson.E{Key:"default", Value:"Other"}, bson.E{Key:"output", Value:bson.D{bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}, bson.E{Key:"names", Value:bson.D{bson.E{Key:"$push", Value:"$name"}}}}}}}}}
/*
[
  {
    $bucket: {
      groupBy: "$age",  
      boundaries: [0, 19, 31, 46, Infinity], 
      default: "Other",  
      output: {
        "count": { $sum: 1 },  
        "names": { $push: "$name" }  
      }
    }
  }
]
*/
aggregation.StageBsonBuilder().Bucket(
    "$age",
    []any{0, 19, 31, 46, math.Inf(1)},
    &types.BucketOptions{
        DefaultKey: "Other",
        Output:     aggregation.BsonBuilder().Sum("count", 1).Push("names", "$name").Build(),
    },
).Build()

For more details, please visit the official documentation: Aggregation Stage Builder | go-mongox.

Aggregation Expressions

The aggregation expression builder is used for easily constructing various expressions of the aggregation pipeline, such as $add, $subtract, etc.

Create a new builder instance with aggregation.BsonBuilder(), then call the appropriate methods to build the expression.

Simple Construction

For a single expression, we directly use functions to build.

// bson.D{bson.E{Key:"isAdult", Value:bson.D{bson.E{Key:"$gte", Value:[]interface {}{"$age", 18}}}}}
/*
{
  "isAdult": {
    "$gte": ["$age", 18]
  }
}
*/
aggregation.Gte("isAdult", "$age", 18)

// bson.D{bson.E{Key:"birthYear", Value:bson.D{bson.E{Key:"$subtract", Value:[]interface {}{2024, "$age"}}}}}
/*
{
  "birthYear": {
    "$subtract": [2024, "$age"]
  }
}
*/
aggregation.Subtract("birthYear", 2024, "$age")

// bson.D{bson.E{Key:"age", Value:bson.D{bson.E{Key:"$gt", Value:[]interface {}{18}}}}}
/*
{
  "age": {
    "$gt": 18
  }
}
*/
aggregation.Gt("age", 18)

For more details, please visit the official documentation: Aggregation Expression Builder | go-mongox.

Complex Construction

For more complex expressions, we use builders for construction.

// bson.D{bson.E{Key:"isAdult", Value:bson.D{bson.E{Key:"$gte", Value:[]interface {}{"$age", 18}}}}, bson.E{Key:"birthYear", Value:bson.D{bson.E{Key:"$subtract", Value:[]interface {}{2024, "$age"}}}}}
/*
{
  "isAdult": {
    "$gte": ["$age", 18]
  },
  "birthYear": {
    "$subtract": [2024, "$age"]
  }
}
*/
aggregation.BsonBuilder().
    Gte("isAdult", "$age", 18).
    Subtract("birthYear", 2024, "$age").Build()

// bson.D{bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}, bson.E{Key:"names", Value:bson.D{bson.E{Key:"$push", Value:"$name"}}}}
/*
{
  "count": {
    "$sum": 1
  },
  "names": {
    "$push": "$name"
  }
}
*/
aggregation.BsonBuilder().Sum("count", 1).Push("names", "$name").Build()

// bson.D{bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}, bson.E{Key:"averageAge", Value:bson.D{bson.E{Key:"$avg", Value:"$age"}}}, bson.E{Key:"names", Value:bson.D{bson.E{Key:"$push", Value:"$name"}}}}
/*{
  "count": {
    "$sum": 1


  },
  "averageAge": {
    "$avg": "$age"
  },
  "names": {
    "$push": "$name"
  }
}
*/
aggregation.BsonBuilder().
    Sum("count", 1).
    Avg("averageAge", "$age").
    Push("names", "$name").Build()

For more details, please visit the official documentation: Aggregation Expression Builder | go-mongox.

bsonx package: Simplifying BSON Data Construction

The bsonx package offers a range of convenient functions and builders for constructing BSON data, aimed at simplifying the BSON data construction process.

Builder

Currently, the bsonx package only provides a bson.D data constructor, DBuilder.

d := bsonx.NewD().Add("name", "Mingyong Chen").Add("name", "Burt")

Functions

Functions simplify the construction of BSON data.

m := bsonx.M("name", "Mingyong Chen")
e := bsonx.E("name", "Mingyong Chen")
d := bsonx.D("name", "Mingyong Chen")
a := bsonx.A("Mingyong Chen", "Mingyong Chen")

For more details, please visit the official documentation: bsonx package | go-mongox.

Conclusion

This article provided a detailed introduction to the bson data construction module within the go-mongox library. go-mongox has designed a variety of BSON builders and functions, offering powerful support for developers constructing BSON data in different scenarios.

Contribute to go-mongox!

With your involvement, go-mongox will become even more powerful!