Mongo - Herbs2mongo
[BETA]
herbs2mongo creates repositories to retrieve and store Entities using Mongo.
Installing
$ npm install @herbsjs/herbs2mongo
Using
connection.js
- MongoDB initialization:
const { MongoClient,Logger } = require('mongodb')
const config = require('./config')
let dbInstance = null
module.exports = async () => {
if (dbInstance) {
return new Promise((resolve) => resolve(dbInstance))
}
const client = await new MongoClient(config.connectionString, {
useNewUrlParser: true,
useUnifiedTopology: true
}).connect()
dbInstance = client.db(config.databaseName)
Logger.setLevel("debug") // set this if you want to debug all queries
return dbInstance
}
itemRepository.js
const { Repository } = require('@herbsjs/herbs2mongo')
const connection = require('connection')
const { Item } = require('../domain/entities/item')
const database = 'herbs2mongo_testdb'
class ItemRepository extends Repository {
constructor() {
super({
entity: Item,
collection: 'aCollection',
database,
ids: ['id'],
mongodb: await connection()
})
}
excludedItemFromLastWeek() {
...
}
}
someUsecase.js
const repo = new ItemRepository()
const ret = await repo.findByID('60edc25fc39277307ca9a7ff')
What is a Repository?
A repository, by definition, 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.
Herbs2mongo Repository
In order to boost productivity, herbs2Mongo provides way to dynamically generate a repository class based on your Entities and other metadata.
These 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.
Following 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).
Why Mongo oficial Driver?
herbs2Mongo is just one of many bridges possible between Herbs and other packages. The 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 here.
Repository setup
const { Repository } = require('@herbsjs/herbs2mongo')
const connection = require('connection') // Mongo initialize instance
const { ProductItem } = require('../domain/entities/productItem')
const database = 'herbs2mongo_testdb'
class YourRepository extends Repository {
constructor() {
super({
entity: ProductItem,
collection: 'product_items',
database,
ids: ['id'],
mongodb: await connection()
})
}
}
}
entity
- The Entity to be used as referenceentity: ProductItem
collection
- The name of the collection in databasetable: 'product_items'
database
- The name of the databasedatabase: 'herbs2mongo_testdb'
ids
- Primary keysFormat:
['fieldName', 'fieldName', ...]
There must be corresponding fields in the entity.
ids: ['id'] // productItem.id
or for composite primary key:
ids: [`customerId`, `productId`] // productItem.customerId , productItem.productId
mongoDB
- mongoDB driver initialize instanceCheck mongoDB documentation
Retrieving and Persisting Data
find
Find entities
Format: .find(options)
where id
is an optional object containing { limit, skip, orderBy, filter }
.
Return: Entity array
const repo = new ItemRepository(injection)
const ret = await repo.find()
Options:
limit
Adds a limit clause to the query.
const repo = new ItemRepository(injection)
const ret = await repo.find({ limit: 10 })
skip
Adds a skip clause to the query..
const repo = new ItemRepository(injection)
const ret = await repo.find({ skip: 5 })
orderBy
Adds an order by clause to the query. Column can be string, or list mixed with string and object...
const repo = new ItemRepository(injection)
const ret = await repo.find({ orderBy: 'description'})
filter
Adds a filter to the query with given values.
const repo = new ItemRepository(injection)
const ret = await repo.find({ filter: { stringTest: ["aString"] } })
findByID
Find entities by IDs
Format: .findByID(id)
where id
is an ObjectId string, this will be changed to _id automaticaly.
Return: Entity array
const repo = new ItemRepository(injection)
const ret = await repo.findByID('60edc25fc39277307ca9a7ff')
insert
Insert an Entity into a table.
Format: .insert(entity)
where entity
is an Entity instance with values to be persisted..
Return: The inserted entity with the values from database.
const repo = new ItemRepository(injection)
const ret = await repo.insert(aNewEntity)
insertMany
Insert an array of Entities into a table.
Format: .insertMany([entity])
where [entity]
is an array of Entities instances with values to be persisted.
Return: The inserted entity with the values from database.
const aNewArrayofEntities = [
givenAnEntity('string one test',false),
givenAnEntity('string two test',true)
]
const repo = new ItemRepository(injection)
const ret = await repo.insertMany(aNewArrayofEntities)
update
Update an Entity.
Format: .update(entity)
where entity
is an Entity instance with values to be persisted.
Return: The updated entity with the values from database.
const repo = new ItemRepository(injection)
const ret = await repo.update(aModifiedEntity)
updateMany
Update a group of Entities.
Format: .updateMany(options)
where options
is a set of conditionals and new values to set a group of entities.
Return: The updated entity with the values from database.
const repo = new ItemRepository(injection)
let filterDefinition = { id: anEntity.id }
let updateDefinition = { $set: { "stringTest" : "everything works very well" } }
await itemRepo.updateMany({ filter: filterDefinition, update: updateDefinition})
deleteByID
Delete an Entity.
Format: .deleteByID(id)
where id
is an ObjectId string, this will be changed to _id automaticaly..
Return: true for success or false for error.
const repo = new ItemRepository(injection)
let filterDefinition = { numberTest : [aModifiedInstance.numberTest] }
const ret = await repo.deleteMany({ filter: filterDefinition })
deleteMany
Delete a group of Entities.
Format: .deleteMany(options = { filter})
where options
is a set of filters to be deleted.
Return: true
for success or false
for error
const repo = new ItemRepository(injection)
let filterDefinition = { numberTest : [aModifiedInstance.numberTest] }
const ret = await repo.deleteMany({ filter: filterDefinition })
delete
Delete an Entitie.
Format: .delete(entity)
where entity
is a Entity instance to be deleted.
Return: true
for success or false
for error
const repo = new ItemRepository(injection)
const ret = await repo.delete(aModifiedEntity)