Does Sequelize support Insert on duplicate key update? - node.js

Is there a Model or Instance method that will perform an insert or update, depending on the whether or not the record exists? Preferably making use of MySQL's "INSERT ON DUPLICATE KEY UPDATE" syntax?

they have recently added this feature upsert or insertOrUpdate
/**
* Insert or update a single row. An update will be executed if a row
* which matches the supplied values on either the primary key or a unique
* key is found. Note that the unique index must be defined in your sequelize
* model and not just in the table. Otherwise you may experience a unique
* constraint violation, because sequelize fails to identify the row that
* should be updated.
*/
Model.upsert({uniqueKey: 1234, name: 'joe'}).then(function () {
// cheer for joy
});

Sequelize does not currently support upsert - I believe it was hard to introduce a good cross dialect solution.
You can however do a findOrCreate and a updateAttributes.
Edit: Sequelize does now support UPSERT with a pretty decent cross dialect implementation, see: https://github.com/sequelize/sequelize/pull/2518

Now you can use upsert in Sequelize

Related

Querying a composite key with multiple IN values with jOOQ

I have the following query:
SELECT *
FROM table
WHERE (id, other_id, status)
IN (
(1, 'XYZ', 'OK'),
(2, 'ZXY', 'OK') -- , ...
);
Is it possible to construct this query in a type-safe manner using jOOQ, preferably without generating composite keys? Is it possible to do this using jOOQ 3.11?
My apologies, it seems my Google-fu was not up to par. The opposite of this question can be found here: Use JOOQ to do a delete specifying multiple columns in a "not in" clause
For completeness' sake, so that other Google searches might be more immediately helpful, the solution is:
// can be populated using DSL.row(...); for each entry
Collection<? extends Row3<Long, String, String>> values = ...
dslContext.selectFrom(TABLE)
.where(DSL.row(ID, OTHER_ID, STATUS).in(values))
.fetch();
Relevant jOOQ documentation: https://www.jooq.org/doc/3.14/manual/sql-building/conditional-expressions/in-predicate-degree-n/
Your own answer already shows how to do this with a 1:1 translation from SQL to jOOQ using the IN predicate for degrees > 1.
Starting from jOOQ 3.14, there is also the option of using the new <embeddablePrimaryKeys/> flag in the code generator, which will produce embeddable types for all primary keys (and foreign keys referencing them). This will help never forget a key column on these queries, which is especially useful for joins.
Your query would look like this:
ctx.selectFrom(TABLE)
.where(TABLE.PK_NAME.in(
new PkNameRecord(1, "XYZ", "OK"),
new PkNameRecord(2, "ZXY", "OK")))
.fetch();
The query generated behind the scenes is the same as yours, using the 3 constraint columns for the predicate. If you add or remove a constraint from the key, the query will no longer compile. A join would look like this:
ctx.select()
.from(TABLE)
.join(OTHER_TABLE)
.on(TABLE.PK_NAME.eq(OTHER_TABLE.FK_NAME))
.fetch();
Or an implicit join would look like this:
ctx.select(OTHER_TABLE.table().fields(), OTHER_TABLE.fields())
.from(OTHER_TABLE)
.fetch();

In Sequelize How to order by `column_a - column_b`?

In my project I am using node.js v10, sequelize 5.8.9 and Postgres 11.
In database there is a Task table and a few child tables. I have done the sequelize model definition, and the create, update, query through sequelize just works perfectly.
Today I was going to make the query ordered by Task.end_time - Task.start_time, sounds easy, doesn't it? However it proved to be very tricky if not impossible using sequelize.
As the options object passed into findAll method contains nested include arrays to retrieve the child tables, the SQL generated actually is complicated and containing subqueries.
I have tried sequelize.literal, sequelize.fn, none worked, and the reasons are the same - sequelize put the ORDER BY clause in two places - one in a subquery where the field names are still in underscored form, e.g. start_time and end_time and the other in the end of the sql, where the field names have been aliased to startTime and endTime, therefore the order I specified can never satisfy both at the same time.
I also think of Sequelize.VIRTUAL data type, found this post however the trick didn't work either. The SQL generated was wrong:
"Task"."endTime - startTime as runningTime" FROM "task"
Any advice / suggestion is appreciated.

Sequelize bulkCreate updateOnDuplicate for postgresQL?

I know there is no support for updateOnDuplicate for postgresQL by Sequelize sequelize doc, so is there a work around for this?
Can it be implemented via "SQL command".
New sequelize (v5) includes updateOnDuplicate feature for all dialects
Fields to update if row key already exists (on duplicate key update)?
(only supported by MySQL, MariaDB, SQLite >= 3.24.0 & Postgres >=
9.5). By default, all fields are updated.
Check here : Docs
You can use as
model.bulkCreate(dataToUpdate, { updateOnDuplicate: ["user_id", "token", "created_at"] })
There is some work around. See upsert function. When used in Postgresql it creates custom function in database. Unfortunately there is no bulkUpsert, so you either use it in some for-loop or execute raw SQL as suggested here.

Waterline - Postgres - DataTypes

I am having difficulties with Waterline models and creating the Postgres tables related to those models.
No matter what I do to create a varchar(n) in the table through a model, it converts the attribute to text. And bigint also is being converted to integer!
Should I change the ORM?
Is there a way to do that?
You can do a more pleasant approach, using Waterline to "RUD" in "CRUD" but not to "C" - create! This because Waterline can be very "bad" at creating intermediary tables, primary keys (composite keys) and etc. So what I do today is this:
Compose a full .sql file archive to create indexes and tables.
Create the database once. (Alter if needed).
Declare all the tables as models. Just insert the type, primary key (if it is a single one) and lifecycle callbacks.
Make sure that config/models.js is set to migrate : safe.
Conclusion: I can insert, read and delete rows with Waterline, but I don't trust it (performance-wise) to create my tables. Sequelize on the other hand is a much more mature ORM and can be used if you need it. For me the hybrid waterline + SQL is sufficient.
EDIT: My models dont have any aggregation (like my_pets: { model: pet} ), just row names and types, as simple as possible.
Sails supported datatype:
String, text, integer, float, date, datetime, boolean, binary, array, json, mediumtext, longtext, objectid
If you need to specify exact length -> varchar(n), you need to use supported data type as shown above, or sails provide option called query.
Model.query() method which you can use to perform any kind of query you want.
var queryString='CREATE TABLE if not exists sailsusers.test (id INT NOT NULL,name VARCHAR(45) NULL,PRIMARY KEY (id))'
Test.query(queryString,function(err,a){
if(err)
return console.log(err);
console.log(a,'\n',b);
res.ok();
});

Subsonic 3 .Save() VS .Update() and .Add()

What is the difference between:
.Save();
.Add();
.Update():
You don't mention which templates you're using (I'm going to assume ActiveRecord), but as a general rule:
Save will insert if the object
IsNew==true or otherwise it will
update.
Add will always insert a new record.
Update will only update an object
with IsNew==false and will fail if
there is no corresponding record in
the db for the instance.

Resources