{"id":13412361,"url":"https://github.com/kamva/mgm","last_synced_at":"2025-05-15T13:08:30.048Z","repository":{"id":38380980,"uuid":"230460014","full_name":"Kamva/mgm","owner":"Kamva","description":"Mongo Go Models (mgm) is a fast and simple MongoDB ODM for Go (based on official Mongo Go Driver)","archived":false,"fork":false,"pushed_at":"2023-12-18T22:59:13.000Z","size":158,"stargazers_count":761,"open_issues_count":16,"forks_count":62,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-05-11T22:40:38.067Z","etag":null,"topics":["go","mgm","model","mongo","mongo-go-models","mongodb","odm"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kamva.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-12-27T14:40:51.000Z","updated_at":"2025-05-06T08:06:13.000Z","dependencies_parsed_at":"2023-02-14T18:16:34.735Z","dependency_job_id":"7d15410a-02a8-4695-a156-792601ecac71","html_url":"https://github.com/Kamva/mgm","commit_stats":{"total_commits":109,"total_committers":10,"mean_commits":10.9,"dds":0.09174311926605505,"last_synced_commit":"2065e2ddaf3331adec79d3ccc74aa2049aa9d4d0"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kamva%2Fmgm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kamva%2Fmgm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kamva%2Fmgm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kamva%2Fmgm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kamva","download_url":"https://codeload.github.com/Kamva/mgm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254346624,"owners_count":22055808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","mgm","model","mongo","mongo-go-models","mongodb","odm"],"created_at":"2024-07-30T20:01:23.863Z","updated_at":"2025-05-15T13:08:25.033Z","avatar_url":"https://github.com/Kamva.png","language":"Go","funding_links":[],"categories":["Database Drivers","数据库驱动程序","Data Integration Frameworks","数据库驱动`连接和操作数据库工具`","数据库驱动"],"sub_categories":["NoSQL Database Drivers","Advanced Console UIs","NoSQL数据库驱动程序","SQL 查询语句构建库"],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg width=\"250\" src=\"https://user-images.githubusercontent.com/22454054/71487214-759cb680-282f-11ea-9bcf-caa663b3e348.png\" /\u003e\n\u003c/p\u003e\n\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://goreportcard.com/report/github.com/Kamva/mgm\"\u003e\n    \u003cimg src=\"https://goreportcard.com/badge/github.com/Kamva/mgm\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://godoc.org/github.com/Kamva/mgm\"\u003e\n    \u003cimg src=\"https://godoc.org/github.com/Kamva/mgm?status.svg\" alt=\"GoDoc\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://travis-ci.com/Kamva/mgm\"\u003e\n    \u003cimg src=\"https://travis-ci.com/Kamva/mgm.svg?branch=master\" alt=\"Build Status\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/Kamva/mgm\"\u003e\n    \u003cimg src=\"https://codecov.io/gh/Kamva/mgm/branch/master/graph/badge.svg\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n  \n\n# Mongo Go Models \n\nThe Mongo ODM for Go\n\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Bugs / Feature Requests](#bugs--feature-request)\n- [Communicate With Us](#communicate-with-us)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n- Define your models and perform CRUD operations with hooks before/after each operation.\n- `mgm` makes Mongo search and aggregation super easy to do in Golang.\n- Just set up your configs once and get collections anywhere you need them.\n- `mgm` predefines all Mongo operators and keys, so you don't have to hardcode them yourself.\n- `mgm` wraps the official Mongo Go Driver.\n\n## Requirements\n- Go 1.17 or higher.\n- MongoDB 3.6 and higher.\n\n## Installation\n\n```bash\ngo get github.com/kamva/mgm/v3\n```\n\n\n## Usage\nTo get started, import the `mgm` package and setup the default config:\n```go\nimport (\n   \"github.com/kamva/mgm/v3\"\n   \"go.mongodb.org/mongo-driver/mongo/options\"\n)\n\nfunc init() {\n   // Setup the mgm default config\n   err := mgm.SetDefaultConfig(nil, \"mgm_lab\", options.Client().ApplyURI(\"mongodb://root:12345@localhost:27017\"))\n}\n```\n\nDefine your model:\n```go\ntype Book struct {\n   // DefaultModel adds _id, created_at and updated_at fields to the Model.\n   mgm.DefaultModel `bson:\",inline\"`\n   Name             string `json:\"name\" bson:\"name\"`\n   Pages            int    `json:\"pages\" bson:\"pages\"`\n}\n\nfunc NewBook(name string, pages int) *Book {\n   return \u0026Book{\n      Name:  name,\n      Pages: pages,\n   }\n}\n```\n\nInsert new document:\n```go\nbook := NewBook(\"Pride and Prejudice\", 345)\n\n// Make sure to pass the model by reference (to update the model's \"updated_at\", \"created_at\" and \"id\" fields by mgm).\nerr := mgm.Coll(book).Create(book)\n```\n\nFind one document \n```go\n// Get the document's collection\nbook := \u0026Book{}\ncoll := mgm.Coll(book)\n\n// Find and decode the doc to a book model.\n_ = coll.FindByID(\"5e0518aa8f1a52b0b9410ee3\", book)\n\n// Get the first doc of the collection \n_ = coll.First(bson.M{}, book)\n\n// Get the first doc of a collection using a filter\n_ = coll.First(bson.M{\"pages\":400}, book)\n```\n\nUpdate a document\n```go\n// Find your book\nbook := findMyFavoriteBook()\n\n// and update it\nbook.Name = \"Moulin Rouge!\"\nerr := mgm.Coll(book).Update(book)\n```\n\nDelete a document\n```go\n// Just find and delete your document\nerr := mgm.Coll(book).Delete(book)\n```\n\nFind and decode a result:\n```go\nresult := []Book{}\n\nerr := mgm.Coll(\u0026Book{}).SimpleFind(\u0026result, bson.M{\"pages\": bson.M{operator.Gt: 24}})\n```\n\n### A Model's Default Fields\nEach model by default (by using `DefaultModel` struct) has\nthe following fields:  \n- `_id` : The document ID.\n\n- `created_at`: The creation date of a doc. When saving a new doc, this is automatically populated by the `Creating` hook.\n- `updated_at`: The last updated date of a doc. When saving a doc, this is automatically populated by the `Saving` hook.\n\nYou can even implement your own default model to customize its fields.\n\n### A Model's Hooks\n\nEach model has the following hooks:\n- `Creating`: Called when creating a new model.\nSignature : `Creating(context.Context) error`\n\n- `Created`: Called after a new model is created.\nSignature : `Created(context.Context) error`\n\n- `Updating`: Called when updating model.\nSignature : `Updating(context.Context) error`\n\n- `Updated` : Called after a model is updated.\nSignature : `Updated(ctx context.Context, result *mongo.UpdateResult) error`\n\n- `Saving`: Called when creating or updating a model.\nSignature : `Saving(context.Context) error`\n\n- `Saved`: Called after a model is created or updated.\nSignature: `Saved(context.Context) error`\n\n- `Deleting`: Called when deleting a model.\nSignature: `Deleting(context.Context) error`\n\n- `Deleted`: Called after a model is deleted.\nSignature: `Deleted(ctx context.Context, result *mongo.DeleteResult) error`\n\n**Notes about hooks**: \n- Each model by default uses the `Creating` and `Saving` hooks, so if you want to define those hooks yourself, remember to invoke the `DefaultModel` hooks from your own hooks.\n- Collection methods that call these hooks:\n\t- `Create` \u0026 `CreateWithCtx`\n\t- `Update` \u0026 `UpdateWithCtx`\n\t- `Delete` \u0026 `DeleteWithCtx`\n\nExample:\n```go\nfunc (model *Book) Creating(ctx context.Context) error {\n   // Call the DefaultModel Creating hook\n   if err := model.DefaultModel.Creating(ctx); err!=nil {\n      return err\n   }\n\n   // We can validate the fields of a model and return an error to prevent a document's insertion.\n   if model.Pages \u003c 1 {\n      return errors.New(\"book must have at least one page\")\n   }\n\n   return nil\n}\n```\n### Configuration\nThe `mgm` default configuration has a context timeout:\n```go\nfunc init() {\n   _ = mgm.SetDefaultConfig(\u0026mgm.Config{CtxTimeout:12 * time.Second}, \"mgm_lab\", options.Client().ApplyURI(\"mongodb://root:12345@localhost:27017\"))\n}\n\n// To get the context, just call the Ctx() method, assign it to a variable\nctx := mgm.Ctx()\n\n// and use it\ncoll := mgm.Coll(\u0026Book{})\ncoll.FindOne(ctx, bson.M{})\n\n// Or invoke Ctx() and use it directly\ncoll.FindOne(mgm.Ctx(), bson.M{})\n``` \n\n\n### Collections\nGet a model's collection:\n```go\ncoll := mgm.Coll(\u0026Book{})\n\n// Do something with the collection\n```\n\n`mgm` automatically detects the name of a model's collection:\n```go\nbook := Book{}\n\n// Print your model's collection name.\ncollName := mgm.CollName(\u0026book)\nfmt.Println(collName) // output: books\n```\n\nYou can also set a custom collection name for your model by implementing the `CollectionNameGetter` interface:\n```go\nfunc (model *Book) CollectionName() string {\n   return \"my_books\"\n}\n\n// mgm returns the \"my_books\" collection\ncoll := mgm.Coll(\u0026Book{})\n```\n\nGet a collection by its name (without needing to define a model for it):\n```go\ncoll := mgm.CollectionByName(\"my_coll\")\n   \n// Do Aggregation, etc. with the collection\n```\n\nCustomize the model db by implementing the `CollectionGetter`\ninterface:\n```go\nfunc (model *Book) Collection() *mgm.Collection {\n    // Get default connection client\n   _, client, _, err := mgm.DefaultConfigs()\n\n   if err != nil {\n      panic(err)\n   }\n\n   db := client.Database(\"another_db\")\n   return mgm.NewCollection(db, \"my_collection\")\n}\n```\n\nOr return a model's collection from another connection:\n\n```go\nfunc (model *Book) Collection() *mgm.Collection {\n   // Create new client\n   client, err := mgm.NewClient(options.Client().ApplyURI(\"mongodb://root:12345@localhost:27017\"))\n\n   if err != nil {\n      panic(err)\n   }\n\n   // Get the model's db\n   db := client.Database(\"my_second_db\")\n\n   // return the model's custom collection\n   return mgm.NewCollection(db, \"my_collection\")\n}\n```\n### Aggregation\nWhile we can use Mongo Go Driver Aggregate features, `mgm` also \nprovides simpler methods to perform aggregations:\n\nRun an aggregation and decode the result:\n```go\nauthorCollName := mgm.Coll(\u0026Author{}).Name()\nresult := []Book{}\n\n// Lookup with just a single line of code\n_ := mgm.Coll(\u0026Book{}).SimpleAggregate(\u0026result, builder.Lookup(authorCollName, \"auth_id\", \"_id\", \"author\"))\n\n// Multi stage (mix of mgm builders and raw stages)\n_ := mgm.Coll(\u0026Book{}).SimpleAggregate(\u0026result,\n\t\tbuilder.Lookup(authorCollName, \"auth_id\", \"_id\", \"author\"),\n\t\tM{operator.Project: M{\"pages\": 0}},\n)\n\n// Do something with result...\n```\n\nDo aggregations using the mongo Aggregation method:\n```go\nimport (\n   \"github.com/kamva/mgm/v3\"\n   \"github.com/kamva/mgm/v3/builder\"\n   \"github.com/kamva/mgm/v3/field\"\n   . \"go.mongodb.org/mongo-driver/bson\"\n   \"go.mongodb.org/mongo-driver/bson/primitive\"\n)\n\n// The Author model collection\nauthorColl := mgm.Coll(\u0026Author{})\n\ncur, err := mgm.Coll(\u0026Book{}).Aggregate(mgm.Ctx(), A{\n    // The S function accepts operators as parameters and returns a bson.M type.\n    builder.S(builder.Lookup(authorColl.Name(), \"author_id\", field.Id, \"author\")),\n})\n```\n\nA more complex example and mixes with mongo raw pipelines:\n```go\nimport (\n   \"github.com/kamva/mgm/v3\"\n   \"github.com/kamva/mgm/v3/builder\"\n   \"github.com/kamva/mgm/v3/field\"\n   \"github.com/kamva/mgm/v3/operator\"\n   . \"go.mongodb.org/mongo-driver/bson\"\n   \"go.mongodb.org/mongo-driver/bson/primitive\"\n)\n\n// Author model collection\nauthorColl := mgm.Coll(\u0026Author{})\n\n_, err := mgm.Coll(\u0026Book{}).Aggregate(mgm.Ctx(), A{\n    // S function get operators and return bson.M type.\n    builder.S(builder.Lookup(authorColl.Name(), \"author_id\", field.Id, \"author\")),\n    builder.S(builder.Group(\"pages\", M{\"books\": M{operator.Push: M{\"name\": \"$name\", \"author\": \"$author\"}}})),\n    M{operator.Unwind: \"$books\"},\n})\n\nif err != nil {\n    panic(err)\n}\n```\n\n### Transactions\n\n- To run a transaction on the default connection use the `mgm.Transaction()` function, e.g:\n```go\nd := \u0026Doc{Name: \"Mehran\", Age: 10}\n\nerr := mgm.Transaction(func(session mongo.Session, sc mongo.SessionContext) error {\n\n   // do not forget to pass the session's context to the collection methods.\n\terr := mgm.Coll(d).CreateWithCtx(sc, d)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn session.CommitTransaction(sc)\n})\n```\n\n- To run a transaction with your own context, use the `mgm.TransactionWithCtx()` method.\n- To run a transaction on another connection, use the `mgm.TransactionWithClient()` method.\n\n-----------------\n## Other Mongo Go Models Packages\n\n**We implemented these packages to simplify queries and aggregations in mongo**\n\n`builder`: simplify mongo queries and aggregations.  \n\n`operator` : contains mongo operators as predefined variables.  \n(e.g `Eq  = \"$eq\"` , `Gt  = \"$gt\"`)  \n\n`field` : contains mongo fields used in aggregations and ... as predefined variable.\n(e.g `LocalField = \"localField\"`, `ForeignField = \"foreignField\"`) \n \nExample:\n ```go\nimport (\n   \"github.com/kamva/mgm/v3\"\n   f \"github.com/kamva/mgm/v3/field\"\n   o \"github.com/kamva/mgm/v3/operator\"\n   \"go.mongodb.org/mongo-driver/bson\"\n)\n\n// Instead of hard-coding mongo operators and fields\n_, _ = mgm.Coll(\u0026Book{}).Aggregate(mgm.Ctx(), bson.A{\n    bson.M{\"$count\": \"\"},\n    bson.M{\"$project\": bson.M{\"_id\": 0}},\n})\n\n// Use the predefined operators and pipeline fields.\n_, _ = mgm.Coll(\u0026Book{}).Aggregate(mgm.Ctx(), bson.A{\n    bson.M{o.Count: \"\"},\n    bson.M{o.Project: bson.M{f.Id: 0}},\n})\n ```\n \n## Bugs / Feature request\nNew features can be requested and bugs can be reported on [Github issue tracker](https://github.com/Kamva/mgm/issues).\n\n## Communicate With Us\n\n* Create new topic at [mongo-go-models Google Group](https://groups.google.com/forum/#!forum/mongo-go-models)  \n* Ask your question or request new feature by creating an issue at [Github issue tracker](https://github.com/Kamva/mgm/issues)  \n\n## Contributing \n\n[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/kamva/mgm)\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FKamva%2Fmgm.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FKamva%2Fmgm?ref=badge_shield)\n\n1. Fork the repository\n1. Clone your fork (`git clone https://github.com/\u003cyour_username\u003e/mgm \u0026\u0026 cd mgm`)\n1. Create your feature branch (`git checkout -b my-new-feature`)\n1. Make changes and add them (`git add .`)\n1. Commit your changes (`git commit -m 'Add some feature'`)\n1. Push to the branch (`git push origin my-new-feature`)\n1. Create new pull request\n\n## License\n\nMongo Go Models is released under the [Apache License](https://github.com/Kamva/mgm/blob/master/LICENSE)\n\n\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FKamva%2Fmgm.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FKamva%2Fmgm?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkamva%2Fmgm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkamva%2Fmgm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkamva%2Fmgm/lists"}