{"id":22474704,"url":"https://github.com/herbsjs/herbs2mongo","last_synced_at":"2025-08-02T11:32:13.461Z","repository":{"id":37004414,"uuid":"385601117","full_name":"herbsjs/herbs2mongo","owner":"herbsjs","description":"Create repositories using Mongo Driver to retrieve and store Entities","archived":false,"fork":false,"pushed_at":"2023-11-23T06:45:44.000Z","size":745,"stargazers_count":1,"open_issues_count":4,"forks_count":8,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-11T21:32:31.216Z","etag":null,"topics":["database","hacktoberfest","mongodb","orm"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/herbsjs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","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":"2021-07-13T12:46:08.000Z","updated_at":"2022-10-03T22:00:29.000Z","dependencies_parsed_at":"2024-06-21T20:20:05.374Z","dependency_job_id":null,"html_url":"https://github.com/herbsjs/herbs2mongo","commit_stats":{"total_commits":60,"total_committers":7,"mean_commits":8.571428571428571,"dds":0.5333333333333333,"last_synced_commit":"d5e0de178062acc70c837f836410dbf8e077d205"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/herbsjs/herbs2mongo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herbsjs%2Fherbs2mongo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herbsjs%2Fherbs2mongo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herbsjs%2Fherbs2mongo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herbsjs%2Fherbs2mongo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/herbsjs","download_url":"https://codeload.github.com/herbsjs/herbs2mongo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herbsjs%2Fherbs2mongo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268378965,"owners_count":24240907,"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-08-02T02:00:12.353Z","response_time":74,"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":["database","hacktoberfest","mongodb","orm"],"created_at":"2024-12-06T13:10:04.287Z","updated_at":"2025-08-02T11:32:13.082Z","avatar_url":"https://github.com/herbsjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CI](https://github.com/herbsjs/herbs2mongo/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/herbsjs/herbs2mongo/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/herbsjs/herbs2mongo/branch/main/graph/badge.svg)](https://codecov.io/gh/herbsjs/herbs2mongo)\n\n# herbs2mongo\n\nherbs2mongo creates repositories to retrieve and store [Entities](https://github.com/herbsjs/gotu) using [MongoDB](https://docs.mongodb.com/drivers/node/current/).\n\n### Installing\n```\n    $ npm install @herbsjs/herbs2mongo\n```\n\n### Using\n\n`connection.js` - MongoDB initialization:\n```javascript\nconst {MongoClient,Logger} = require('mongodb')\nconst config = require('./config')\n\nlet dbInstance = null\n\nmodule.exports = async () =\u003e {\n  if (dbInstance) {\n      return new Promise((resolve) =\u003e resolve(dbInstance))\n  }\n  const client = await new MongoClient(config.connectionString).connect()\n  dbInstance = client.db(config.databaseName)\n  Logger.setLevel(\"debug\") // set this if you want to debug all queries\n  return dbInstance\n}\n\n```\n\n`itemRepository.js`:\n```javascript\nconst { Repository } = require('@herbsjs/herbs2mongo')\nconst connection = require('connection')\nconst { Item } = require('../domain/entities/item')\nconst database = 'herbs2mongo_testdb'\n\nclass ItemRepository extends Repository {\n    constructor() {\n        super({\n            entity: Item,\n            collection: 'aCollection',\n            database,\n            ids: ['id'],\n            mongodb: connection\n        })\n    }\n\n    excludedItemFromLastWeek() {\n        ...\n    }\n}\n```\n\n`someUsecase.js`:\n```javascript\nconst repo = new ItemRepository()\nconst ret = await repo.findByID('60edc25fc39277307ca9a7ff') // note that the id is equivalent to ObjectId _id field\n```\n\n### What is a Repository?\n\nA repository, by [definition](https://en.wikipedia.org/wiki/Domain-driven_design#Building_blocks), is part of the layer to retrieve and store entities abstracting the underlying implementation. By using repositories, details of these implementation such as relational database, document-oriented databases, etc, should not leak to the domain code. In other words, no raw SQL queries on your use case or entity files.\n\n### herbs2Mongo Repository\n\nIn order to boost productivity herbs2Mongo provides way to dynamically generate a repository class based on your Entities and other metadata.\n\nThese metadata are necessary to close the gap between OOP concepts and paradigms and those of relational databases. For example, it is necessary to specify primary keys and foreign keys as these information do not exist in the description of your domain.\n\nFollowing Herbs architecture principals it is not the intention of this lib to create yet another ODM or query builder but to create a bridge between your domain and an existing one (from Mongo).\n\n### Why Mongo oficial Driver?\n\nherbs2Mongo is just one of many bridges possible between Herbs and other packages.\n\nThe advantage of using Mongo is that is a simple and flexible way to retrieve data from MongoDB, as a plus we're using the [oficial driver from MongoDB](https://www.mongodb.com/docs/drivers/node/current/) here.\n\n### Repository setup\n\n```javascript\nconst { Repository } = require('@herbsjs/herbs2mongo')\nconst connection = require('connection')  // Mongo initialize instance\nconst { ProductItem } = require('../domain/entities/productItem')\nconst database = 'herbs2mongo_testdb'\n\nclass YourRepository extends Repository {\n    constructor() {\n        super({\n            entity: ProductItem,\n            collection: 'product_items',\n            database,\n            ids: ['id'],\n            mongodb: connection\n        })\n    }\n}\n```\n\n- `entity` - The [Entity](https://github.com/herbsjs/gotu) to be used as reference\n\n    ```javascript\n    entity: ProductItem\n    ```\n\n- `collection` - The name of the collection in database\n\n    ```javascript\n    collection: 'product_items'\n    ```\n\n- `database` - The name of the database\n\n    ```javascript\n    database: 'herbs2mongo_testdb'\n    ```\n\n- `ids` - Primary keys\n\n    Format: `['fieldName', 'fieldName', ...]`\n\n    There must be corresponding fields in the entity.\n\n    ```javascript\n    ids: ['id']  // productItem.id\n    ```\n\n    or for composite primary key:\n\n    ```javascript\n    ids: [`customerId`, `productId`]  // productItem.customerId , productItem.productId\n    ```\n\n- `mongoDB` - mongoDB driver initialize instance\n\n    Check mongoDB [documentation](https://docs.mongodb.com/drivers/node/v3.6/)\n\n\n\n## Retrieving and Persisting Data\n\n### `find`\nFind entities\n\nFormat: `.find(options)` where `options` is a optional object containing `{ limit, skip, orderBy, filter }`\n\nReturn: Entity array\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.find()\n```\n\nOptions:\n\n- `limit`\nAdds a limit clause to the query.\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.find({ limit: 10 })\n```\n\n- `skip`\nAdds an skip clause to the query.\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.find({ offset: 5 })\n```\n\n- `orderBy`\nAdds an order by clause to the query. Column can be string, or list mixed with string and object.\n\n```javascript\n// order by collum\nconst repo = new ItemRepository(injection)\nconst ret = await repo.find({ orderBy: 'description'})\n```\n\n- `filter`\nAdds a filter to the query with given values.\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.find({ filter: { stringTest: [\"aString\"] } })\n```\n\n- `find with native parameters`\nYou also can use the method find to use the mongoDB [native parameters](https://www.mongodb.com/docs/manual/reference/method/db.collection.find/)\n\n```javascript\nconst { ObjectId } = require('mongodb')\n\nconst repo = new ItemRepository(injection)\nconst ret = await repo.find({ _id : { $in : [ObjectId('4323fefwed4234'), ObjectId('3432d23232dfff')] } } )\n```\n\n```javascript\nconst { ObjectId } = require('mongodb')\n\nconst repo = new ItemRepository(injection)\nconst ret = await repo.find({ _id : { $in : [ObjectId('4323fefwed4234'), ObjectId('3432d23232dfff')] } } )\n```\n\n- `findAll`\nYou also findAll records using the native find without filters\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.find({ } )\n```\n\n\n### `findByID`\nFind entities by IDs\n\nFormat: `.findByID(id)` where `id` is a ObjectId string or array, this will be changed to _id automaticaly\n\nReturn: Entity array\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.findByID('60edc25fc39277307ca9a7ff')\n```\nor \n```javascript\n\n const ids = [\n            '60edc25fc39277307ca9a7ff',\n            '80edd25fc39272307ca9a712',\n          ]\n\nconst repo = new ItemRepository(injection)\nconst ret = await repo.findByID(ids)\n```\n\n\n\n### `insert`\n\nInsert an Entity into a table.\n\nFormat: `.insert(entity)` where `entity` is a Entity instance with values to be persisted.\n\nReturn: The inserted entity with the values from database.\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.insert(aNewEntity)\n```\n\n\n### `insertMany`\n\nInsert an array of Entities into a table.\n\nFormat: `.insertMany([entity])` where `[entity]` is a array of Entities instances with values to be persisted.\n\nReturn: The inserted id's in ObjectId format with the values from database.\n\n```javascript\n\nconst aNewArrayofEntities = [\n  givenAnEntity('string one test',false),\n  givenAnEntity('string two test',true)\n]\n\nconst repo = new ItemRepository(injection)\nconst ret = await repo.insertMany(aNewArrayofEntities)\n```\n\n### `update`\n\nUpdate an Entity.\n\nFormat: `.update(entity)` where `entity` is a Entity instance with values to be persisted.\n\nReturn: The updated entity with the values from database.\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.update(aModifiedEntity)\n```\n\n\n### `updateMany`\n\nUpdate a group of Entities.\n\nFormat: `.updateMany(options)` where `options` is a set of conditionals and new values to set a group of entities\n\nReturn: The updated entity with the values from database.\n\n```javascript\nconst repo = new ItemRepository(injection)\nlet filterDefinition = { id: anEntity.id  }\nlet updateDefinition = { $set: { \"stringTest\" : \"everything works very well\" } }\nawait itemRepo.updateMany({ filter: filterDefinition, update: updateDefinition})\n\n```\n\n### `deleteByID`\n\nDelete an Entity.\n\nFormat: `.deleteByID(id)` where `id` is a ObjectId string, this will be changed to _id automaticaly.\n\nReturn: `true` for success or `false` for error\n\n```javascript\nconst repo = new ItemRepository(injection)\nconst ret = await repo.deleteByID(entity)\n```\n\n### `deleteMany`\n\nDelete a group of Entities.\n\nFormat: `.deleteMany(options = { filter})` where `options` is a set of filters to be deleted.\n\nReturn: `true` for success or `false` for error\n\n```javascript\n\nconst repo = new ItemRepository(injection)\nlet filterDefinition = {  numberTest : [aModifiedInstance.numberTest] }\nconst ret = await repo.deleteMany({ filter: filterDefinition })\n\n```\n\n### `delete`\n\nDelete an Entitie.\n\nFormat: `.delete(entity)` where `entity` is a Entity instance to be deleted.\n\nReturn: `true` for success or `false` for error\n\n```javascript\n\nconst repo = new ItemRepository(injection)\nconst ret = await repo.delete(aModifiedEntity)\n```\n\n\n## TODO\n\n- [ ] Allow only scalar types for queries (don't allow entity / object types)\n- [ ] Allow to ommit database name\n\nFeatures:\n- [ ] Be able to change the conventions (injection)\n- [ ] Exclude / ignore fields on all query statement\n- [ ] Awareness of created/updated at/by fields\n- [X] Plug-and-play MongoDB\n\nRetrieving and Persist:\n- [X] insert\n    - [X] batchs (insertMany)\n- [X] update\n    - [X] batchs (updateMany)\n- [X] delete (id)\n    - [X] batchs (deleteMany)\n- [ ] persist (upsert)\n- [X] find (ID)\n    - [ ] deal with entities / tables with custom _ids\n- [X] find by (any field)\n    - [ ] deal with entities / tables with custom _ids\n    - [X] order by\n    - [X] limit\n    - [X] skip\n- [X] find All\n    - [X] order by\n    - [X] limit\n    - [X] skip\n- [X] find with pages\n- [ ] agregations\n- [ ] replace\n- [ ] collation\n- [ ] watch\n- [ ] first\n- [ ] last\n\nTests:\n- [X] Pure JS\n- [X] MongoDB\n\n### Contribute\nCome with us to make an awesome *herbs2mongo*.\n\nNow, if you do not have the technical knowledge and also have intended to help us, do not feel shy, [click here](https://github.com/herbsjs/herbs2mongo/issues) to open an issue and collaborate their ideas, the contribution may be a criticism or a compliment (why not?)\n\nIf you would like to help contribute to this repository, please see [CONTRIBUTING](https://github.com/herbsjs/herbs2mongo/blob/main/.github/CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherbsjs%2Fherbs2mongo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fherbsjs%2Fherbs2mongo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherbsjs%2Fherbs2mongo/lists"}