{"id":20802431,"url":"https://github.com/ajclopez/mgs","last_synced_at":"2025-05-07T01:03:46.344Z","repository":{"id":200604243,"uuid":"705895864","full_name":"ajclopez/mgs","owner":"ajclopez","description":"Convert URL query parameters to MongoDB queries","archived":false,"fork":false,"pushed_at":"2024-06-23T00:31:55.000Z","size":34,"stargazers_count":12,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-07T01:01:57.534Z","etag":null,"topics":["golang","golang-library","mongodb","mongodb-query-language","query","query-builder","query-language","url-parser"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ajclopez.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,"publiccode":null,"codemeta":null}},"created_at":"2023-10-16T22:57:37.000Z","updated_at":"2025-02-09T05:49:47.000Z","dependencies_parsed_at":"2023-10-29T18:31:54.791Z","dependency_job_id":null,"html_url":"https://github.com/ajclopez/mgs","commit_stats":null,"previous_names":["ajclopez/mgs"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajclopez%2Fmgs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajclopez%2Fmgs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajclopez%2Fmgs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajclopez%2Fmgs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ajclopez","download_url":"https://codeload.github.com/ajclopez/mgs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252793664,"owners_count":21805057,"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":["golang","golang-library","mongodb","mongodb-query-language","query","query-builder","query-language","url-parser"],"created_at":"2024-11-17T18:31:46.718Z","updated_at":"2025-05-07T01:03:46.326Z","avatar_url":"https://github.com/ajclopez.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Go Reference](https://pkg.go.dev/badge/github.com/ajclopez/mgs.svg)](https://pkg.go.dev/github.com/ajclopez/mgs) [![GitHub release (with filter)](https://img.shields.io/github/v/release/ajclopez/mgs)](https://github.com/ajclopez/mgs/releases) [![Go Report](https://goreportcard.com/badge/ajclopez/mgs)](https://goreportcard.com/report/ajclopez/mgs) [![codecov](https://codecov.io/gh/ajclopez/mgs/graph/badge.svg?token=PGKFDNP677)](https://codecov.io/gh/ajclopez/mgs) [![MIT License][license-shield]][license-url]\n\n\u003cp align=\"center\"\u003e\n  \u003ch3 align=\"center\"\u003eMongo Golang Search\u003c/h3\u003e\n  \u003cp align=\"center\"\u003e\n    Mongo Golang Search provides a query language to a MongoDB database.\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/ajclopez/mgs#usage\"\u003e\u003cstrong\u003eExplore the docs\u003c/strong\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/ajclopez/mgs/issues\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/ajclopez/mgs/issues\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n-------------------------\n\n# Mongo Golang Search (mgs)\n\n### Content index\n\n- [What is this?](#what-is-this)\n- [Getting Started](#getting-started)\n  - [Installation](#installation)\n- [Usage](#usage)\n- [Supported features](#supported-features)\n  - [Filtering](#filtering)\n  - [Pagination](#pagination)\n  - [Sorting](#sorting)\n  - [Projection](#projection)\n  - [Advanced queries](#advanced-queries)\n- [Available options](#available-options)\n  - [Customize limit value](#customize-limit-value)\n  - [Specify casting per param keys](#specify-casting-per-param-keys)\n- [Contributing](#contributing)\n- [License](#license)\n\n## What is this?\n\nMongo Golang Search provides a simple query language to perform advanced searches for your collections in **MongoDB**.\n\nYou could also use **Mongo Golang Search** to searching, sorting, pagination and combining logical operators.\n\n## Getting Started\n\n### Installation\n\nThe recommended way to get started using the Mongo Golang Search is by using Go modules to install the dependency in your project. This can be done either by importing packages from github.com/ajclopez/mgs and having the build step install the dependency or by explicitly running\n\n```go\ngo get github.com/ajclopez/mgs\n```\n\n## Usage\n\nTo get started with mgs, import the mgs package and implement the Primitives ObjectID function which is used to convert strings to ObjectID.\n\n```go\ntype Primitives struct{}\n\nfunc (primitives *Primitives) ObjectID(oidStr string) (interface{}, error) {\n\treturn ObjectID() // invoke ObjectID from MongoDB Driver\n}\n```\n\nThen create an instance of `QueryHandler`:\n\n```go\nqueryHandler := mgs.NewQueryHandler(\u0026Primitives{})\n```\n\nFinally use a mgs.MongoGoSearch function:\n\n```go\nqueryHandler.MongoGoSearch(query string, opts *FindOptions)\n```\n\n##### Arguments\n\n`query`: query string part of the requested API URL.\n\n`opts`: object for advanced configuration [See below](#available-options) [optional].\n\nUsing `mgs.MongoGoSearch` function with [mongo-go-driver](https://github.com/mongodb/mongo-go-driver) library to filter, sort, limit and skip in MongoDB:\n\n```go\nimport (\n    \"context\"\n\n    \"github.com/ajclopez/mgs\"\n    \"go.mongodb.org/mongo-driver/bson/primitive\"\n    \"go.mongodb.org/mongo-driver/mongo/options\"\n)\n\ntype Primitives struct{}\n\nfunc (primitives *Primitives) ObjectID(oidStr string) (interface{}, error) {\n\treturn primitive.ObjectIDFromHex(oidStr)\n}\n\nqueryHandler := mgs.NewQueryHandler(\u0026Primitives{})\n\nopts := mgs.FindOption()\nresult, err := queryHandler.MongoGoSearch(query, opts)\n\n...\n\nfindOpts := options.Find()\nfindOpts.SetLimit(result.Limit)\nfindOpts.SetSkip(result.Skip)\nfindOpts.SetSort(result.Sort)\nfindOpts.SetProjection(result.Projection)\n\ncur, err := collection.Find(context.TODO(), result.Filter, findOpts)\n\n...\n```\n\nUsing optional configurations:\n\n```go\nimport (\n    \"context\"\n\n    \"github.com/ajclopez/mgs\"\n    \"go.mongodb.org/mongo-driver/bson/primitive\"\n    \"go.mongodb.org/mongo-driver/mongo/options\"\n)\n\ntype Primitives struct{}\n\nfunc (primitives *Primitives) ObjectID(oidStr string) (interface{}, error) {\n\treturn primitive.ObjectIDFromHex(oidStr)\n}\n\nqueryHandler := mgs.NewQueryHandler(\u0026Primitives{})\n\nopts := mgs.FindOption()\nopts.SetCaster(map[string]mgs.CastType{\n\t\"mobile\": mgs.STRING,\n})\nopts.SetMaxLimit(1000)\nopts.SetDefaultLimit(10)\nresult, err := queryHandler.MongoGoSearch(query, opts)\n\n...\n\nfindOpts := options.Find()\nfindOpts.SetLimit(result.Limit)\nfindOpts.SetSkip(result.Skip)\nfindOpts.SetSort(result.Sort)\nfindOpts.SetProjection(result.Projection)\n\ncur, err := collection.Find(context.TODO(), result.Filter, findOpts)\n\n...\n```\n\n##### Example\n\nA request of the form:\n\n```js\n'employees?status=sent\u0026date\u003e2020-01-06T14:00:00.000Z\u0026author.firstname=Jhon\u0026skip=50\u0026limit=100\u0026sort=-date\u0026fields=id,date';\n```\n\nIs translated to:\n\n```Go\nQuery{\n    Filter: map[string]interface{}{\n        \"author.firstname\":     \"John\",\n        \"date\":                 map[string]interface{}{\"$gt\": \"2020-01-06T14:00:00.000Z\"},\n        \"status\":               \"SENT\",\n    },\n    Sort:  map[string]int{\n        \"date\": 1,\n        \"id\": 1\n    },\n    Limit: 100,\n    Skip:  50,\n}\n```\n\n## Supported features\n\n### Filtering\n\n| Operator  | URI                  | Example                         |\n| --------- | -------------------- | ------------------------------- |\n| `$eq`     | `key=val`            | `type=public`                   |\n| `$ne`     | `key!=val`           | `status!=SENT`                  |\n| `$gt`     | `key\u003eval`            | `price\u003e5`                       |\n| `$gte`    | `key\u003e=val`           | `price\u003e=9`                      |\n| `$lt`     | `key\u003cval`            | `date\u003c2020-01-01T14:00:00.000Z` |\n| `$lte`    | `key\u003c=val`           | `priority\u003c=-5`                  |\n| `$in`     | `key=val1,val2`      | `status=QUEUED,DEQUEUED`        |\n| `$nin`    | `key!=val1,val2`     | `status!=QUEUED,DEQUEUED`       |\n| `$exists` | `key`                | `email`                         |\n| `$exists` | `!key`               | `!email`                        |\n| `$regex`  | `key=/value/\u003copts\u003e`  | `email=/@gmail\\.com$/`          |\n| `$regex`  | `key!=/value/\u003copts\u003e` | `phone!=/^58/`                  |\n\n### Pagination\n\nUseful to limit the number of records returned.\n\n- Operator keys are `skip` and `limit`.\n- Use `limit` operator to limit the number of records returned.\n- Use `skip` operator to skip the specified number of records.\n\n```json\nskip=20\u0026limit=10\n```\n\n### Sorting\n\nUseful to sort returned records.\n\n- Operator key is `sort`.\n- It accepts a comma-separated list of fields.\n- Use `-` prefixes to sort in descending order.\n- Use `+` prefixes to sort in ascedending order.\n\n```json\nsort=id,-date\n```\n\n### Projection\n\nUseful to limit fields to return in each records.\n\n- Operator key is `fields`.\n- It accepts a comma-separated list of fields.\n\n```json\nfields=firstname,lastname,phone,email\n```\n\n**Note:**\n\n- The `_id` field (returned by default).\n\n### Advanced queries\n\nFor more advanced usage (`and`, `or` logic operations), pass query `filter` as string with the logical operations, for example:\n\n```json\nfilter=(country=Mexico OR country=Spain) and gender=female\n```\n\n##### What operations are possible?\n\n- Filtering operations.\n- The `AND/and` operator.\n- The `OR/or` operator.\n- Parenthesis can be used for grouping.\n\n## Available options\n\nYou can use advanced options:\n\n```go\nopts := mgs.FindOption()\nopts.SetCaster(map[string]mgs.CastType{\n\t\"mobile\": mgs.STRING,\n})\nopts.SetMaxLimit(100)\nopts.SetDefaultLimit(10)\n```\n\n- `FindOption` creates a new FindOptions instance.\n- `SetCaster` object to specify custom casters, key is the caster name, and value is a type (`BOOLEAN, NUMBER, PATTERN, DATE, STRING`).\n- `SetDefaultLimit` which contains custom value to return records.\n- `SetMaxLimit` which contains custom value to return a maximum of records.\n\n### Customize limit value\n\nYou can specify your own maximum or default limit value.\n\n- `defaultLimit`: custom value to return records.\n- `maxLimit`: custom value to return a maximum of records.\n\n```go\nopts := mgs.FindOption()\nopts.SetMaxLimit(1000)\nopts.SetDefaultLimit(10)\n\nresult, err := mgs.MongoGoSearch(\"city=Madrid\u0026skip=10\u0026limit=1000\", opts)\n```\n\n### Specify casting per param keys\n\nYou can specify how query parameter values are casted by passing an object.\n\n- `casters`: object which map keys to casters.\n\n```go\nopts := mgs.FindOption()\nopts.SetCaster(map[string]mgs.CastType{\n\t\"key1\": mgs.STRING,\n    \"key2\": mgs.NUMBER,\n    \"key3\": mgs.STRING,\n    \"key4\": mgs.BOOLEAN\n})\n\nresult, err := mgs.MongoGoSearch(\"key1=VALUE\u0026key2=10\u0026key3=20\u0026key4=true\", opts)\n```\n\n## Contributing\n\nShould you like to provide any feedback, please open up an Issue, I appreciate feedback and comments. Any contributions you make are **greatly appreciated**.\n\n1. Fork the Project\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing-feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nThis software is released under the MIT license. See `LICENSE` for more information.\n\n[license-shield]: https://img.shields.io/badge/License-MIT-yellow.svg\n[license-url]: https://github.com/ajclopez/mgs/blob/master/LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajclopez%2Fmgs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fajclopez%2Fmgs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajclopez%2Fmgs/lists"}