Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: multi_create method for bulk records #406

Closed
davydovanton opened this issue May 21, 2017 · 7 comments
Closed

Proposal: multi_create method for bulk records #406

davydovanton opened this issue May 21, 2017 · 7 comments

Comments

@davydovanton
Copy link
Member

davydovanton commented May 21, 2017

Now we can use #create method for this. But I think it will be better to create the different method for this. We should use #command here. If you don't mind, I can create PR for this 馃憤

How we can use in in projects:

repo = BookRepository.new
books = repo.multi_create([{ title: 'Hanami' }, { title: 'Ruby' }])
books # => array of entity 
@jodosha
Copy link
Member

jodosha commented May 22, 2017

I'm not for expanding repository public API to bulk operations, because it's a gateway for "find", "update", "delete" in bulk feature requests.

As they aren't common use case, developers can implement by their own, and/or use upcoming Hanami::Model::Command /cc @hlegius

@jodosha jodosha closed this as completed May 22, 2017
@jodosha jodosha self-assigned this May 22, 2017
@jodosha
Copy link
Member

jodosha commented May 22, 2017

@davydovanton PS Please use the forum for proposals and please leave GH issues for actionable tickets that we have already agreed on. Thank you very much. 馃挌

@spectator
Copy link

As they aren't common use case, developers can implement by their own, and/or use upcoming Hanami::Model::Command

@jodosha would you point me to a direction how something like multi_create can be implemented w/o upcoming Hanami::Model::Command ?

@mereghost
Copy link
Member

@spectator You can plug directly on rom commands, be aware that the following line won't update your created_at and updated_at fields

class SomeRepository < Hanami::Repository
  def bulk_insert(data)
    command(:create, somes, result: :many).call(data)
  end
end

@spectator
Copy link

Thanks a lot @mereghost ! I led myself too deep into ROM commands and completely overlooked something as simple as this. BTW, you can add timestamps plugin like so

class SomeRepository < Hanami::Repository
  def bulk_insert(data)
    command(:create, somes, use: [:timestamps], result: :many).call(data)
  end
end

@solnic
Copy link
Member

solnic commented Jun 25, 2017

rom-rb may use a bulk insert whenever you pass in a collection of tuples (or structs, doesn't matter). It of course depends on the db backend, so ie on PG we use multi_insert which does a bulk insert on the database side. This is completely transparent from the user point of view because each adapter may provide custom command subclasses for each database type. It's also worth to mention that in rom-rb there's no concept of inserting a single tuple / struct, it always operates on collections of data, even when you pass in a single tuple it'll be put it into a single-element array and pass down to dataset backend, if its size is > 1 multi insert will be used.

...anyhow, what I'm trying to say is that there's absolutely no need for a special bulk insert API because rom-rb handles it for you, and if you don't like that it's implicit, you can always drop down to the relation API and call multi_insert yourself.

Here's what I'm talking about (using rom-4 from master):

[3] pry(main)> users = rom.relations[:users]
=> #<ROM::Relation[Users] name=ROM::Relation::Name(users) dataset=#<Sequel::Postgres::Dataset: "SELECT \"id\", \"name\" FROM \"users\" ORDER BY \"users\".\"id\"">>
[4] pry(main)> users.command(:create).call(name: "Jane")
I, [2017-06-25T16:36:49.128106 #23731]  INFO -- : (0.082191s) INSERT INTO "users" ("name") VALUES ('Jane') RETURNING *
=> {:id=>2, :name=>"Jane"}
[5] pry(main)> users.command(:create, result: :many).call([{name: "Jane"}, {name: "John"}])
I, [2017-06-25T16:37:15.031153 #23731]  INFO -- : (0.000187s) BEGIN
I, [2017-06-25T16:37:15.031634 #23731]  INFO -- : (0.000386s) INSERT INTO "users" ("name") VALUES ('Jane'), ('John') RETURNING *
I, [2017-06-25T16:37:15.032716 #23731]  INFO -- : (0.000964s) COMMIT
=> [{:id=>5, :name=>"Jane"}, {:id=>6, :name=>"John"}]

@spectator
Copy link

@solnic I see what you mean, but hanami-repository always returns one result even though collection of tuples was passed into create and rom-rb of course created all those records in the database, and thus the need for special bulk insert API so I can get full result back.

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

No branches or pull requests

5 participants