Skip to content

Instantly share code, notes, and snippets.

@twolfson
Last active December 28, 2019 22:38
Show Gist options
  • Save twolfson/13eeeb547271c8ee32707f7b02c2ed90 to your computer and use it in GitHub Desktop.
Save twolfson/13eeeb547271c8ee32707f7b02c2ed90 to your computer and use it in GitHub Desktop.
Node.js ORM evaluation

We are planning on building a Node.js service. Here's our evaluation of the current ORM landscape:

Last updated: May 2 2016

Our likely choice is sequelize (possibly with callback bindings via bluebird-nodeify)

@heisian
Copy link

heisian commented Mar 7, 2019

Objection is much better architected than Sequelize. Objection is based off of Laravel's Eloquent, which is based off of Rails' ActiveRecord. Both pieces of software are very good. Objection is easily extensible due to its class-based architecture.

Many other users who've had experience in both Sequelize and Objection.js (as I have) are in the same boat: Vincit/objection.js#1069

@aprat84
Copy link

aprat84 commented Apr 4, 2019

Should also consider TypeORM.

@stalniy
Copy link

stalniy commented Apr 7, 2019

@jamespedid
Copy link

jamespedid commented Apr 11, 2019

I can't fathom how anyone would say that Objection is a good ORM and Sequelize is a bad ORM. Objection has so many bad practices going for it, it's practically a nightmare. Now there is a disclaimer that I've used Sequelize for much longer than Objection, but just from an API perspective I absolutely loathe Objection. Building it as an extension to Knex.js is just a terrible idea for an ORM.

For those who are having trouble with Sequelize's ORM for associations, what is difficult about:

const { Product, Order } = sequelize.models;
MyModel.findAll({
    include: [{
        model: Order,
        as: 'orders'
    }]
})

Hell, even if you have to do three or four associations deep, it isn't hard because you just add more objects with more includes. Constrast that to Objections, where I have to lay out the join ahead of time. Add in some goofy relationship 'magic' and you have a mess on your hands.

Raw SQL? Sequelize makes it a breeze to execute a raw query and map them to a model. And the queries that Sequelize generate typically are good (except for a few questionable subquery choices, but you can remedy these with a simple subQuery: true option.)

@elhigu
Copy link

elhigu commented Apr 14, 2019

Objection has so many bad practices going for it, it's practically a nightmare.

Please elaborate. I haven't got chance to hear any negative critic about it and that would be really valuable. Only thing I could think of is that it promotes using knex migrations which are not really nice.

@koskimas
Copy link

@jamespedid Here's the objection equivalent of your example.

const { MyModel } = require('./models/MyModel')

MyModel.query().eager('orders')

here's a four layers deep association fetch

const { MyModel } = require('./models/MyModel')

MyModel.query().eager('orders.someRelation.somethingElse.evenDeeperRelation')

Could you please elaborate what you mean by goofy magic and stuff?

@jamespedid
Copy link

First goofy thing: 'orders' is the name of the SQL table. Why am i littering everywhere in my code with the names of tables? Isn't the ORM supposed to abstract away such details? Even worse, what if I have to change the table in the database? Not unheard of, pretty common as applications tend to age actually. Maybe I'm refactoring and moving schemas. Having implementation details of the database bleed into my code everywhere is a huge problem for me.

Second goofy thing: the awkward DSL of using something like '[why,is,this,an,array,in,a,string]' to eagerly fetch over these entities? Again, incredibly hard to work with in a long-term setting. Having tokenizable, refactorable pieces in a way that is convenient is a big deal. I could use something like [${Why.tableName},${Is.tableName},...], but this is already becoming far more cumbersome than sequelize.

Copy link

ghost commented May 12, 2019

@jamespedid orders is not the SQL table name, it is the relation name defined under MyModel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment