I'm writing an application that is on top of a PostgreSQL database so I am using pg.js. This is my first experience working with SQL and I wasn't aware of ORMs like Sequelize so I just started writing raw SQL. I tried to go the ORM route after I had built a lot of things but to be honest it felt quite limiting - especially because I have some complex queries that don't really seem to fit into Sequelize.However, I am finding it difficult to organize my code. I want an ORM like structure because it is organized, but I want to work with my own custom queries.Right now my application is structured like the following:- Routes -> api calls - Controllers -> get the data Ideally there would be models, but I have not implemented that. As a result I have fat controllers that take request parameters from the router, get data, and return it. Sometimes this is mixed with business logic.For example:// Project Controller const getProject = async (req, res) => res.send(await client.query(`select * from project where project.id = ${req.params.id}`)) const createProject = async (req, res) => { // Insert project if does not exist // Add people to project // Send emails // Return project data } So the first function is a simple retrieval, but the second function will have a lot more logic mixed into it and will be pulling from other domains that are not the project (users and sending emails).I'm aiming for fat models thin controllers instead:// Project Controller const getProject = async (req, res) => res.send(await Project.findById(req.params.projectId)) const createProject = async (req, res) => { // Project.create will do all of the business logic from previous example const { projectMembers, projectName, ...moreProjectDetails } = req.body const project = new Project({ projectName, ...moreProjectDetails }) res.send(await project.create({ projectMembers }) } // Project Model class ProjectModel { constructor({ ...projectDetails }) { // all the project details } createProject({ projectMembers }) { // Insert project if does not exist db.client.query(`insert project...`) // Add people to project // Send emails // Return project data } } The problem I have with the way the model looks, which is based off of examples I see is that people tend to do database logic inside of the model. So now can you not only hydrate a Project object but you can also use it to find any other project in the DBproject = new Project({ id: 5, name: 'foo' }) otherProject = await project.findById({ id: 10 }) But I think this makes more sense to doproject = new Project({ id: 5, name: 'foo' }) response = Db.findProjectById(project) response2 = Db.insertProject(project) const { status, data } = response; console.log(status) // success console.log(data) // ({ id: 5, name: 'foo', description: 'foo', members: [], ...otherDetails }) This way the controllers are still thin, the models represent your database objects, but concerns are also separated as you have a Database object that handles that domain.I find it weird that in the examples I see people mix database logic with the models - it seems bloated this way. But this is also what something like Sequelize seems to do which is turning me away from it.Any thoughts or suggestions? If I want to go with the last example I provided, would I just create a database class that handles all of the heavy lifting and have models that are only concerned with representing their data and validation? The Database class would generate all of the sql.
Submitted August 06, 2019 at 11:56AM by 1_over_f
No comments:
Post a Comment