{"id":39033703,"url":"https://github.com/zebresel-com/mongodm","last_synced_at":"2026-01-17T17:42:28.446Z","repository":{"id":57486285,"uuid":"45905544","full_name":"zebresel-com/mongodm","owner":"zebresel-com","description":"A golang object document mapper (ODM) for MongoDB","archived":false,"fork":false,"pushed_at":"2019-01-24T17:18:15.000Z","size":73,"stargazers_count":198,"open_issues_count":14,"forks_count":32,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-08-13T21:30:34.118Z","etag":null,"topics":["document-mapper","golang","golang-library","mapper","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":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zebresel-com.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-11-10T10:45:43.000Z","updated_at":"2025-07-06T16:37:21.000Z","dependencies_parsed_at":"2022-09-01T22:31:15.837Z","dependency_job_id":null,"html_url":"https://github.com/zebresel-com/mongodm","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/zebresel-com/mongodm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebresel-com%2Fmongodm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebresel-com%2Fmongodm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebresel-com%2Fmongodm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebresel-com%2Fmongodm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zebresel-com","download_url":"https://codeload.github.com/zebresel-com/mongodm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebresel-com%2Fmongodm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28513972,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["document-mapper","golang","golang-library","mapper","mongodb","odm"],"created_at":"2026-01-17T17:42:28.338Z","updated_at":"2026-01-17T17:42:28.413Z","avatar_url":"https://github.com/zebresel-com.png","language":"Go","readme":"[![Build Status](https://travis-ci.org/zebresel-com/mongodm.svg?branch=master)](https://travis-ci.org/zebresel-com/mongodm)\n[![GoDoc](https://godoc.org/github.com/zebresel-com/mongodm?status.svg)](https://godoc.org/github.com/zebresel-com/mongodm)\n\n## What is mongodm?\n\nThe mongodm package is an object document mapper (ODM) for mongodb written in Go which uses the official mgo adapter.\nYou can find an **example API application** [here](https://github.com/moehlone/mongodm-example).\n\n![Heisencat](https://octodex.github.com/images/heisencat.png)\n\n## Features\n\n- 1:1, 1:n struct relation mapping and embedding\n- call `Save()`,`Update()`, `Delete()` and `Populate()` directly on document instances\n- call `Select()`, `Sort()`, `Limit()`, `Skip()` and `Populate()` directly on querys\n- validation (default and custom with regular expressions) followed by translated error list (customizable)\n- population instruction possible before and after querys\n- `Find()`, `FindOne()` and `FindID()`\n- default handling for `ID`, `CreatedAt`, `UpdatedAt` and `Deleted` attribute\n- extends `*mgo.Collection`\n- default localisation (fallback if none specified)\n- database authentication (user and password)\n- multiple database hosts on connection\n\n## Todos\n\n- recursive population\n- add more validation presets (like \"email\")\n- benchmarks\n- accept plain strings as objectID value\n- virtuals and hooks (like in mongoose)\n\n## Usage\n\n### Note(!)\n\n`Collection` naming in this package is switched to `Model`.\n\n### Fetch (terminal)\n\n`go get github.com/zebresel-com/mongodm`\n\n### Import\n\nAdd `import \"github.com/zebresel-com/mongodm\"` in your application file.\n\n### Define your own localisation for validation\n\nFirst step is to create a language file in your application (skip if you want to use the english defaults).\nThis is necessary for document validation which is always processed.\nThe following entrys are all keys which are currently used. If one of the keys is not defined the output will be the key itself. In the next step you have to specify a translation map when creating a database connection. \n\nFor example:\n\n```json\n{\n    \"en-US\": {\n        \"validation.field_required\": \"Field '%s' is required.\",\n        \"validation.field_invalid\": \"Field '%s' has an invalid value.\",\n        \"validation.field_invalid_id\": \"Field '%s' contains an invalid object id value.\",\n        \"validation.field_minlen\": \"Field '%s' must be at least %v characters long.\",\n        \"validation.field_maxlen\": \"Field '%s' can be maximum %v characters long.\",\n        \"validation.entry_exists\": \"%s already exists for value '%v'.\",\n        \"validation.field_not_exclusive\": \"Only one of both fields can be set: '%s'' or '%s'.\",\n        \"validation.field_required_exclusive\": \"Field '%s' or '%s' required.\"\n    }\n}\n```\n\n### Create a database connection\n\nSubsequently you have all information for mongodm usage and can now connect to a database.\nLoad your localisation file and parse it until you get a `map[string]string` type. Then set the database host and name. Pass the config reference to the mongodm `Connect()` method and you are done.\n(You dont need to set a localisation file or credentials)\n\n```go\n\tfile, err := ioutil.ReadFile(\"locals.json\")\n\n\tif err != nil {\n\t\tfmt.Printf(\"File error: %v\\n\", err)\n\t\tos.Exit(1)\n\t}\n\n\tvar localMap map[string]map[string]string\n\tjson.Unmarshal(file, \u0026localMap)\n\n\tdbConfig := \u0026mongodm.Config{\n\t\tDatabaseHosts: []string{\"127.0.0.1\"},\n\t\tDatabaseName: \"mongodm_sample\",\n\t\tDatabaseUser: \"admin\",\n\t\tDatabasePassword: \"admin\",\n\t\t// The option `DatabaseSource` is the database used to establish \n\t\t// credentials and privileges with a MongoDB server. Defaults to the value\n\t\t// of `DatabaseName`, if that is set, or \"admin\" otherwise.\n\t\tDatabaseSource: \"admin\",\n\t\tLocals:       localMap[\"en-US\"],\n\t}\n\n\tconnection, err := mongodm.Connect(dbConfig)\n\n\tif err != nil {\n\t\tfmt.Println(\"Database connection error: %v\", err)\n\t}\n```\n\nYou can also pass a custom DialInfo from mgo ([`*mgo.DialInfo`](https://godoc.org/labix.org/v2/mgo#DialInfo)). If used, all config attributes starting with `Database` will be ignored:\n\n```go\n\tfile, err := ioutil.ReadFile(\"locals.json\")\n\n\tif err != nil {\n\t\tfmt.Printf(\"File error: %v\\n\", err)\n\t\tos.Exit(1)\n\t}\n\n\tvar localMap map[string]map[string]string\n\tjson.Unmarshal(file, \u0026localMap)\n\n\tdbConfig := \u0026mongodm.Config{\n\t\tDialInfo: \u0026mgo.DialInfo{\n\t\t\tAddrs:    []string{\"127.0.0.1\"},\n\t\t\tTimeout:  3 * time.Second,\n\t\t\tDatabase: \"mongodm_sample\",\n\t\t\tUsername: \"admin\",\n\t\t\tPassword: \"admin\",\n\t\t\tSource:   \"admin\",\n\t\t},\n\t\tLocals:       localMap[\"en-US\"],\n\t}\n\n\tconnection, err := mongodm.Connect(dbConfig)\n\n\tif err != nil {\n\t\tfmt.Println(\"Database connection error: %v\", err)\n\t}\n```\n\n### Create a model\n\n```go\npackage models\n\nimport \"github.com/zebresel-com/mongodm\"\n\ntype User struct {\n\tmongodm.DocumentBase `json:\",inline\" bson:\",inline\"`\n\n\tFirstName string       `json:\"firstname\" bson:\"firstname\"`\n\tLastName  string       `json:\"lastname\"\t bson:\"lastname\"`\n\tUserName  string       `json:\"username\"\t bson:\"username\"`\n\tMessages  interface{}  `json:\"messages\"\t bson:\"messages\" \tmodel:\"Message\" relation:\"1n\" autosave:\"true\"`\n}\n```\n\nIt is important that each schema embeds the IDocumentBase type (mongodm.DocumentBase) and make sure that it is tagged as 'inline' for json and bson.\nThis base type also includes the default values id, createdAt, updatedAt and deleted. Those values are set automatically from the ODM.\nThe given example also uses a relation (User has Messages). Relations must always be from type interface{} for storing bson.ObjectId OR a completely\npopulated object. And of course we also need the related model for each stored message:\n\n```go\ntype Message struct {\n\tmongodm.DocumentBase `json:\",inline\" bson:\",inline\"`\n\n\tSender \t  string       `json:\"sender\" \t bson:\"sender\"`\n\tReceiver  string       `json:\"receiver\"\t bson:\"receiver\"`\n\tText  \t  string       `json:\"text\"\t bson:\"text\"`\n}\n```\nNote that when you are using relations, each model will be stored in his own collection. So the values are not embedded and instead stored as object ID\nor array of object ID's.\n\nTo configure a relation the ODM understands three more tags:\n\n\tmodel:\"Message\"\n\n\t\tThis must be the struct type you want to relate to.\n\n\t\tDefault: none, must be set\n\n\trelation:\"1n\"\n\n\t\tIt is important that you specify the relation type one-to-one or one-to-many because the ODM must decide whether it accepts an array or object.\n\n\t\tPossible: \"1n\", \"11\"\n\t\tDefault: \"11\"\n\n\tautosave:\"true\"\n\n\t\tIf you manipulate values of the message relation in this example and then call 'Save()' on the user instance, this flag decides if this is possible or not.\n\t\tWhen autosave is activated, all relations will also be saved recursively. Otherwise you have to call 'Save()' manually for each relation.\n\n\t\tPossible: \"true\", \"false\"\n\t\tDefault: \"false\"\n\nBut it is not necessary to always create relations - you also can use embedded types:\n\n```go\ntype Customer struct {\n\tmongodm.DocumentBase `json:\",inline\" bson:\",inline\"`\n\n\tFirstName string       `json:\"firstname\" bson:\"firstname\"`\n\tLastName  string       `json:\"lastname\"\t bson:\"lastname\"`\n\tAddress   *Address     `json:\"address\"\t bson:\"address\"`\n}\n\ntype Address struct {\n\n\tCity \tstring       `json:\"city\" \t bson:\"city\"`\n\tStreet  string       `json:\"street\"\t bson:\"street\"`\n\tZipCode\tint16\t     `json:\"zip\"\t bson:\"zip\"`\n}\n```\n\nPersisting a customer instance to the database would result in embedding a complete address object. You can embed all supported types.\n\nNow that you got some models and a connection to the database you have to register these models for the ODM for working with them.\n\n### Register your models (collections)\n\nIt is necessary to register your created models to the ODM to work with. Within this process\nthe ODM creates an internal model and type registry to work fully automatically and consistent.\nMake sure you already created a connection. Registration expects a pointer to an IDocumentBase\ntype and the collection name where the docuements should be stored in. Register your collections only once at runtime!\n\nFor example:\n\n```go\nconnection.Register(\u0026User{}, \"users\")\nconnection.Register(\u0026Message{}, \"messages\")\nconnection.Register(\u0026Customer{}, \"customers\")\n```\n\n### Working on a model (collection)\n\nTo create actions on each collection you have to request a model instance.\nMake sure that you registered your collections and schemes first, otherwise it will panic.\n\nFor example:\n\n```go\nUser := connection.Model(\"User\")\n\nUser.Find() ...\n```\n\n### Persist a new document in a collection\n\n`Save()` persists all changes for a document. Populated relations are getting converted to object ID's / array of object ID's so you dont have to handle this by yourself.\nUse this function also when the document was newly created, if it is not existent the method will call insert. During the save process createdAt and updatedAt gets also automatically persisted.\n\nFor example:\n\n```go\nUser := connection.Model(\"User\")\n\nuser := \u0026models.User{}\n\nUser.New(user) //this sets the connection/collection for this type and is strongly necessary(!) (otherwise panic)\n\nuser.FirstName = \"Max\"\nuser.LastName = \"Mustermann\"\n\nerr := user.Save()\n```\n\n### FindOne\n\nIf you want to find a single document by specifing query options you have to use this method. The query param expects a map (e.g. bson.M{}) and returns a query object which has to be executed manually. Make sure that you pass an IDocumentBase type to the exec function. After this you obtain the first matching object. You also can check the error if something was found.\n\nFor example:\n\n```go\nUser := connection.Model(\"User\")\n\nuser := \u0026models.User{}\n\nerr := User.FindOne(bson.M{\"firstname\" : \"Max\", \"deleted\" : false}).Populate(\"Messages\").Exec(user)\n\nif _, ok := err.(*mongodm.NotFoundError); ok {\n\t//no records were found\n} else if err != nil {\n\t//database error\n} else {\n\tfmt.Println(\"%v\", user)\n}\n```\n\n### Find\n\nUse`Find()` if you want to fetch a set of matching documents. Like FindOne, a map is expected as query param, but you also can call this method without any arguments. When the query is executed you have to pass a pointer to a slice of IDocumentBase types.\n\nFor example:\n\n```go\nUser := connection.Model(\"User\")\n\nusers := []*models.User{}\n\nerr := User.Find(bson.M{\"firstname\" : \"Max\", \"deleted\" : false}).Populate(\"Messages\").Exec(\u0026users)\n\nif _, ok := err.(*mongodm.NotFoundError); ok { //you also can check the length of the slice\n\t//no records were found\n} else if err != nil {\n\t//database error\n} else {\n\tfor user, _ := range users {\n\t\tfmt.Println(\"%v\", user)\n\t}\n}\n```\n\n### FindId\n\nIf you have an object ID it is possible to find the matching document with this param.\n\nFor example:\n\n```go\nUser := connection.Model(\"User\")\n\nuser := \u0026models.User{}\n\nerr := User.FindId(bson.ObjectIdHex(\"55dccbf4113c615e49000001\")).Select(\"firstname\").Exec(user)\n\nif _, ok := err.(*mongodm.NotFoundError); ok {\n\t//no records were found\n} else if err != nil {\n\t//database error\n} else {\n\tfmt.Println(\"%v\", user)\n}\n```\n\n### Populate\n\nThis method replaces the default object ID value with the defined relation type by specifing one or more field names. After it was succesfully populated you can access the relation field values. Note that you need type assertion for this process.\n\nFor example:\n\n```go\nUser := connection.Model(\"User\")\n\nuser := \u0026models.User{}\n\nerr := User.Find(bson.M{\"firstname\" : \"Max\"}).Populate(\"Messages\").Exec(user)\n\nif err != nil {\n\tfmt.Println(err)\n}\n\nfor _, user := range users {\n\n\tif messages, ok := user.Messages.([]*models.Message); ok {\n\n\t\tfor _, message := range messages {\n\n\t\t\tfmt.Println(message.Sender)\n\t\t}\n\t} else {\n\t\tfmt.Println(\"something went wrong during type assertion. wrong type?\")\n\t}\n}\n```\nor after your query only for single users:\n\n```go\nUser := connection.Model(\"User\")\n\nuser := \u0026models.User{}\n\nerr := User.Find(bson.M{\"firstname\" : \"Max\"}).Exec(user)\n\nif err != nil {\n\tfmt.Println(err)\n}\n\nfor index, user := range users {\n\n\tif user.FirstName == \"Max\" {\n\n\t\terr := user.Populate(\"Messages\")\n\n\t\tif err != nil {\n\t\t\n\t\t\tfmt.Println(err)\n\t\t\t\n\t\t} else if messages, ok := user.Messages.([]*models.Message); ok {\n\t\n\t\t\tfor _, message := range messages {\n\t\n\t\t\t\tfmt.Println(message.Text)\n\t\t\t}\n\t\t} else {\n\t\t\tfmt.Println(\"something went wrong during type assertion. wrong type?\")\n\t\t}\n\t}\n}\n```\n\nNote: Only the first relation level gets populated! This process is not recursive.\n\n### Default document validation\n\nTo validate model attributes/values you first have to define some rules.\nTherefore you can add **tags**:\n\n```go\ntype User struct {\n\tmongodm.DocumentBase `json:\",inline\" bson:\",inline\"`\n\n\tFirstName    string   `json:\"firstname\"  bson:\"firstname\" minLen:\"2\" maxLen:\"30\" required:\"true\"`\n\tLastName     string   `json:\"lastname\"  bson:\"lastname\" minLen:\"2\" maxLen:\"30\" required:\"true\"`\n\tUserName     string   `json:\"username\"  bson:\"username\" minLen:\"2\" maxLen:\"15\"`\n\tEmail        string   `json:\"email\" bson:\"email\" validation:\"email\" required:\"true\"`\n\tPasswordHash string   `json:\"-\" bson:\"passwordHash\"`\n\tAddress      *Address `json:\"address\" bson:\"address\"`\n}\n```\n\nThis User model defines, that the firstname for example must have a minimum length of 2 and a maximum length of 30 characters (**minLen**, **maxLen**). Each **required** attribute says, that the attribute can not be default or empty (default value is required:\"false\"). The **validation** tag is used for regular expression validation. Currently there is only one preset \"email\". A use case would be to validate the model after a request was mapped:\n\n```go\nUser := self.db.Model(\"User\")\nuser := \u0026models.User{}\n\nerr, _ := User.New(user, self.Ctx.Input.RequestBody)\n\nif err != nil {\n\tself.response.Error(http.StatusBadRequest, err)\n\treturn\n}\n\nif valid, issues := user.Validate(); valid {\n\n\t\terr = user.Save()\n\t\t\n\t\tif err != nil {\n\t\t\tself.response.Error(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\t\n\t\t// Go on..\n\t\t\n\t} else {\n\t\tself.response.Error(http.StatusBadRequest, issues)\n\t\treturn\n\t}\n```\n\nThis example maps a received `Ctx.Input.RequestBody` to the attribute values of a new user model. Continuing with calling `user.Validate()` we detect if the document is valid and if not what issues we have (a list of validation errors). Each `Save` call will also validate the current state. The document gets only persisted when there were no errors.\n\n### Custom document validation\n\nIn some cases you may want to validate request parameters which do not belong to the model itself or you have to do advanced validation checks. Then you can hook up before default validation starts:\n\n```go\nfunc (self *User) Validate(values ...interface{}) (bool, []error) {\n\n\tvar valid bool\n\tvar validationErrors []error\n\n\tvalid, validationErrors = self.DefaultValidate()\n\n\ttype m map[string]string\n\n\tif len(values) \u003e 0 {\n\n\t\t//expect password as first param then validate it with the next rules\n\t\tif password, ok := values[0].(string); ok {\n\n\t\t\tif len(password) \u003c 8 {\n\n\t\t\t\tself.AppendError(\u0026validationErrors, mongodm.L(\"validation.field_minlen\", \"password\", 8))\n\n\t\t\t} else if len(password) \u003e 50 {\n\n\t\t\t\tself.AppendError(\u0026validationErrors, mongodm.L(\"validation.field_maxlen\", \"password\", 50))\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tself.AppendError(\u0026validationErrors, mongodm.L(\"validation.field_required\", \"password\"))\n\t\t}\n\t}\n\n\tif len(validationErrors) \u003e 0 {\n\t\tvalid = false\n\t}\n\n\treturn valid, validationErrors\n}\n```\nSimply add a `Validate` method in your `IDocumentBase` type model with the signature\n`Validate(...interface{}) (bool, []error)`. Within this you can implement any checks that you want. You can call the `DefaultValidate` method first to run all default validations. You will get a `valid` and `validationErrors` return value.\nNow you can run your custom checks and append some more errors with `AppendError(*[]error, message string)`. Also have a look at the `mongodm.L` method if you need language localisation! The next example shows how we can use our custom validate method:\n\n```go\nUser := self.db.Model(\"User\")\n\tuser := \u0026models.User{}\n\n\t// NOTE: we now want our request body get back as a map (requestMap)..\n\terr, requestMap := User.New(user, self.Ctx.Input.RequestBody)\n\n\tif err != nil {\n\t\tself.response.Error(http.StatusBadRequest, err)\n\t\treturn\n\t}\n\n\t//NOTE: ..and validate the \"password\" parameter which is not part of the model/document\n\tif valid, issues := user.Validate(requestMap[\"password\"]); valid {\n\t\terr = user.Save()\n\t\t\n\t\tif err != nil {\n\t\t\tself.response.Error(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t} else {\n\t\tself.response.Error(http.StatusBadRequest, issues)\n\t\treturn\n\t}\n\n\tself.response.AddContent(\"user\", user)\n\tself.response.SetStatus(http.StatusCreated)\n\tself.response.ServeJSON()\n}\n```\nIn this case we retrieve a `requestMap` and forward the `password` attribute to our `Validate` method (example above). \nIf you want to use your own regular expression as attribute tags then use the following format: `validation:\"/YOUR_REGEX/YOUR_FLAG(S)\"` - for example: `validation:\"/[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\\.[a-z]{2,4}/\"`\n\n## Contribute\n\nRead this and feel free :-)\n\n### Dockerized\n\nWith docker, you do not need to install `go`  and `mongodb` on your local machine, it's easy to setup a development environment for this repository. Thanks to @centsent who helped to dockerize this project.\n\n### Prerequisites\n\nMake sure you already installed below programs on your local machine:\n\n* `git`\n* `docker`\n* `docker-compose`\n\n### dep\n\n[dep](https://github.com/golang/dep) is a prototype dependency management tool for Go.\nTo use `dep` in the container, prefix `make` for all `dep` commands, for example:\n\n```bash\n$ make dep \"ensure -add github.com/some/repos\"\n```\n\nBeware that the double quotes are required after `make dep` command.\n\n### Making Changes\n\nPuppet has some good and simple [contribution rules](https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md#making-changes) so lets adopt them in an adjusted way.\n\n* Create a topic branch from where you want to base your work.\n  * This is usually the master branch.\n  * To quickly create a topic branch based on master, run `git checkout -b\n    fix/master/my_contribution master`. Please avoid working directly on the\n    `master` branch.\n* Make commits of logical and atomic units.\n* Check for unnecessary whitespace with `git diff --check` before committing.\n* Make sure your commit messages are in a proper format:\n  ```\n  chore: add Oyster build script\n  docs: explain hat wobble\n  feat: add beta sequence\n  fix: remove broken confirmation message\n  refactor: share logic between 4d3d3d3 and flarhgunnstow\n  style: convert tabs to spaces\n  test: ensure Tayne retains clothing\n  ```\n   [(Source)](https://gist.githubusercontent.com/mutewinter/9648651/raw/77f8abd031d02f822543992a86bf4c1fc50ad760/commit_format_examples.txt)\n* Make sure you have added the necessary tests for your changes.\n* Run _all_ the tests with `make test` to assure nothing else was accidentally broken (it will build the docker container and run `go test`)\n\n## Questions?\n\nAre there any questions or is something not clear enough? Simply open up a ticket or send me an email :)\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzebresel-com%2Fmongodm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzebresel-com%2Fmongodm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzebresel-com%2Fmongodm/lists"}