Hacker News new | ask | show | jobs
by nemothekid 2998 days ago
As far as Go ORMs go, there isn’t a decent one that handles what I consider a killer feature of ORMs - relationships. I think sqlx is good enough for most, but I once inherited a project that the management wanted to rewrite off of Scala to Go. Some of the relationships were so complex that hand writing complex joins would have been challenging. Gorm came closest, but it’s “eager fetching” features executes n+1 queries rather than joins.
6 comments

Yes yes and yes. Unless the usecase is truly as simple as CRUD with a single model (in which case I reach for gorm), The easiest road often seems to be just using sqlx and hand-writing the inserts/updates.
What about 90% of cases being simple CRUD and 10% you just do the usual "raw SQL query"?

I've chosen this path of using only sqlx on my current work project (only me) and regret it, because so much typing..

I also work alone on a Go service and have some complex models. I used Gorm and then for complex selects broke out the raw sql. It works okay, I’m still having to bolt on things like OCC and Versioning to my models. I’m glad I used it though- it gave me a solid foundation to work off and replace the bits that don’t quite work well.
I use Masterminds' squirrel library to build up queries which cuts down on the amount of hand written SQL I need.
toyorm support half hand-writing you can bind the model and use its field in sql e.g https://github.com/bigpigeon/toyorm/blob/master/examples/sim...
In that case, just copy the SQLAlchemy design.

It has a functional API and an ORM API, and have a very rich set of join strategies available.

Pop has some support for associations:

https://github.com/markbates/pop

Appears unmaintained? "This repository has been archived by the owner. It is now read-only."
> I think sqlx is good enough for most

sqlx is nice but I wish it had query logging.

It's relatively easy to write a wrapper around your sqlx DB that logs queries before sending them to the underlying sqlx DB. I agree it would be nice to be built in, but then you're kind of locked into the logging interface(s) sqlx supports.
now toyorm support join operation
you means use join to query and output data as table? otherwise I think “eager fetching” is better way
Lets say I have a relationship where a User has one Profile.

    type User Struct { Id int ProfileId int Profile Profile }
    type Profile Struct { Id int }
For a load like this:

    var u User
    db.Model(&User{}).Preload("Profile").Where("id = ?", 7).Take(&u)
Gorm will do something like this:

    SELECT * FROM users WHERE id=7;
    SELECT * FROM profiles WHERE id=7;
Where a join would be more desirable (only involves 1 trip to the db):

    SELECT * FROM users JOIN profiles ON profiles.id=users.profileid WHERE users.id=7
This also has a huge effect on when your initial queries aren't restricted by ID. Gorm will do huge "id IN (1,2,3,4)" queries - or sometimes if I need to filter on a relation (i.e. get users where profile.foo = bar), I end up doing the join getting that data anyways, then the eager queries loads that data again.
In "OneToOne" and "BelongTo" Join is match but in "ManyToMany" and "OneToMany" will generate duplicate data

I think add Join method and only support "One Data" preload is good way