I'd like to perform a batch update using Knex.js
For example:
'UPDATE foo SET [theValues] WHERE idFoo = 1'
'UPDATE foo SET [theValues] WHERE idFoo = 2'
with values:
{ name: "FooName1", checked: true } // to `idFoo = 1`
{ name: "FooName2", checked: false } // to `idFoo = 2`
I was using node-mysql previously, which allowed multiple-statements. While using that I simply built a mulitple-statement query string and just send that through the wire in a single run.
I'm not sure how to achieve the same with Knex. I can see batchInsert
as an API method I can use, but nothing as far as batchUpdate
is concerned.
Note:
I can do an async iteration and update each row separately. That's bad cause it means there's gonna be lots of roundtrips from the server to the DB
I can use the
raw()
thing of Knex and probably do something similar to what I do with node-mysql. However that defeats the whole knex purpose of being a DB abstraction layer (It introduces strong DB coupling)
So I'd like to do this using something "knex-y".
Any ideas welcome.
Assuming you have a collection of valid keys/values for the given table:
To call it
Are you unfortunately subject to non-conventional column names? No worries, I got you fam:
To call it
I needed to perform a batch update inside a transaction (I didn't want to have partial updates in case something went wrong). I've resolved it the next way:
You have a good idea of the pros and cons of each approach. I would recommend a raw query that bulk updates over several async updates. Yes you can run them in parallel, but your bottleneck becomes the time it takes for the db to run each update. Details can be found here.
Below is an example of an batch upsert using knex.raw. Assume that records is an array of objects (one obj for each row we want to update) whose values are the properties names line up with the columns in the database you want to update:
This answer does a great job explaining the runtime relationship between the two approaches.
Edit:
It was requested that I show what
records
would look like in this example.Please note that if your
record
has additional properties than the ones you specified in the query, you cannot do:Because you will hand too many values to the query per record and knex will fail to match the property values of each record with the
?
characters in the query. You instead will need to explicitly push the values on each record that you want to insert into an array like so:There are less repetitive ways of doing the above explicit references, but this is just an example. Hope this helps!