{"id":20665652,"url":"https://github.com/thinkr-open/mongooser","last_synced_at":"2025-07-26T18:04:04.009Z","repository":{"id":69754273,"uuid":"468689670","full_name":"ThinkR-open/mongooser","owner":"ThinkR-open","description":"A port of MongooseJS to R ","archived":false,"fork":false,"pushed_at":"2023-06-20T20:38:54.000Z","size":28,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-19T19:08:23.290Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThinkR-open.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2022-03-11T09:37:39.000Z","updated_at":"2023-07-25T08:11:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"fea83d9d-3123-4c55-b46c-56eb52be12de","html_url":"https://github.com/ThinkR-open/mongooser","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ThinkR-open/mongooser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThinkR-open%2Fmongooser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThinkR-open%2Fmongooser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThinkR-open%2Fmongooser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThinkR-open%2Fmongooser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThinkR-open","download_url":"https://codeload.github.com/ThinkR-open/mongooser/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThinkR-open%2Fmongooser/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267205989,"owners_count":24052762,"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","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-16T19:33:03.665Z","updated_at":"2025-07-26T18:04:03.956Z","avatar_url":"https://github.com/ThinkR-open.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\",\n  eval = TRUE,\n  error = TRUE\n)\n```\n\n# mongooser\n\n\u003c!-- badges: start --\u003e\n\u003c!-- badges: end --\u003e\n\n[WIP / DO NOT USE IN PRODUCTION]\n\nThe goal of mongooser is to port [mongoosejs](https://mongoosejs.com/) to R, for a more, predictable use of MongoDB in a production context.\n\n## Installation\n\nYou can install the development version of mongooser like so:\n\n``` r\npak::pak(\"thinkr-open/mongooser\")\n```\n\n### What's wrong with `{mongolite}`?\n\nNothing, `{mongooser}` is actually built on top of it.\n\n### Ok, so why?\n\nAn issue with MongoDB is that it doesn't enforce any kind of schema, and R isn't very well equiped to handle unstructured data.\n\nAlso, given that it's unstructured and does the type conversion for you, you can get unexpected results when using MongoDB with R.\n\nAnd on top of that, human tend to be a little bit lazy, and if the db allows them to insert random unstructured elements in the db, well, they'll do it, and then some data engineer will cry and scream to scrap and restructure the data to be usable.\n\nHere is a simple example:\n\n```{r eval = TRUE, error = TRUE}\nsystem(\"docker run -p 27017:27017 -d mongo\")\nSys.sleep(10)\n```\n\n```{r include=FALSE}\nmongolite::mongo()$drop()\n```\n\n```{r}\nfridge \u003c- mongolite::mongo()\nmonday_meal \u003c- list(\n  day = Sys.Date() + 1,\n  ingredient = c(\"tofu\", \"brocoli\"),\n  to_reheat = TRUE,\n  box = \"blue\"\n)\n\nfridge$insert(monday_meal)\n```\n\n```{r}\nclass(monday_meal)\n\nfridge_find \u003c- fridge$find()\n\nclass(fridge_find)\n\nfridge_iterate \u003c- fridge$iterate()$one()\n\nclass(fridge_iterate)\n```\n\nIt's even more intersting if you look at the detail structure of each element:\n\n```{r}\ndplyr::glimpse(monday_meal)\ndplyr::glimpse(fridge_find)\ndplyr::glimpse(fridge_iterate)\n```\n\nLet's insert another list:\n\n```{r}\ntuesday_meal \u003c- list(\n  day = Sys.Date() + 2,\n  ingredient = \"pasta\",\n  box = \"red\"\n)\n\nfridge$insert(tuesday_meal)\n```\n\nDepending on what you query, you won't get the same structure:\n\n```{r eval = TRUE, echo = TRUE}\ndplyr::glimpse(\n  fridge$iterate('{\"box\": \"blue\"}')$one()\n)\n```\n\n```{r eval = TRUE, echo = TRUE}\ndplyr::glimpse(\n  fridge$iterate('{\"box\": \"red\"}')$one()\n)\n```\n\n\nAs MongoDB \u0026 `{mongolite}` doesn't inforce any kind of type on read/write, it can be hard to rely on the output.\n\n`{mongooser}` tries to solve that issue by porting [mongoosejs](https://mongoosejs.com/), an object modeling tooling for MongoDB and NodeJS, to R.\n\n## Here is an example\n\n```\ndocker run -d -p 2811:27017 mongo:3.4\n```\n\nThe comments are the correponding mongoosejs codes\n\n```{r eval = TRUE}\n# const mongoose = require('mongoose');\nlibrary(mongooser)\n\n# mongoose.connect(\"mongodb://127.0.0.1:27017/test\")\nmongooser_connect(\n  db = \"test\",\n  url = \"mongodb://localhost\",\n  verbose = FALSE,\n  options = mongolite::ssl_options()\n)\n```\n\nWe'll then build a model, which is a schema for our data:\n\n```{r}\n# const Cat = mongoose.model('Cat', { name: String });\nFood \u003c- model(\n  \"Food\",\n  properties = list(\n    day = \\(x) structure(NA_real_, class = \"Date\"),\n    ingredient = character,\n    box = character,\n    to_reheat = logical\n  ),\n  validator = list(\n    day = lubridate::ymd,\n    ingredient = as.character,\n    box = as.character,\n    to_reheat = as.logical\n  )\n)\n```\n\nLet's empty our collection first:\n\n```{r eval = TRUE}\nFood$drop()\n```\n\nHere, properties is a list of function that returns a data type.\nIt should be one of base R data type, or a function that returns a datatype.\nIf you want to build your own properties, it should be a function that takes one argument (the lenght) and return a repetition of that data type.\n\nYou can then create an instance of that model and save it:\n\n```{r eval = TRUE}\nmonday \u003c- Food$new(\n  monday_meal\n)\nmonday$save()\n\ntuesday \u003c- Food$new(\n  tuesday_meal\n)\ntuesday$save()\n```\n\nThen, you can query the model:\n\n```{r eval = TRUE, echo = TRUE}\ndplyr::glimpse(\n  Food$find()\n)\n```\n\nList the number of items :\n\n```{r eval = TRUE, echo = TRUE}\nFood$count_documents()\n```\n\nQuery one item with `find_one()`.\nNote that this will return the first element matching the query, that does not mean that there are no other records matching this query:\n\n```{r}\nFood$find_one()\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthinkr-open%2Fmongooser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthinkr-open%2Fmongooser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthinkr-open%2Fmongooser/lists"}