2

Suppose we have a such structure in NodeJs Sequelize.

var User = sequelize.define('user', {/* ... */})
var Project = sequelize.define('project', {/* ... */})

Project.hasMany(User)

In this part of video presenter offers to save embedded objects with two steps using promises. In our case it would be something like:

Project.create({
  ...
  }).then(function(project){
     User.create({
        ...
        projectId:project.id
     })
   })

But this approach will result two db calls.

So, is it possible to save embedded objects (Project which contains User e.g. User must have Project's id as a foreign key) into the db with one db call or within a transaction using Sequelize?

1 Answer 1

5

You should be able to insert parent-children by passing an array of objects into a key with the same name as the "as" value used on the "include". Although the documentation is light on the usage, you can see it handled in the source code here.

No promises (pun semi-intended) that this is actually run in single SQL query, not sure of the exact implementation in Sequelize. You should be able to enable logging (logging: console.log in the Sequelize(options)) to see what it's running.

// specify an "as" value and require a User.project_id value
Project.hasMany(User, { as: 'Users', foreignKey: { allowNull: false } });

// define your Project -> Users as json with the "as" value as the key
const project = {
  name: 'project name',
  Users: [
    {
      name: 'user 1',
    },
    {
      name: 'user 2',
    },
  ],
};

// create a transaction and "include" the Model in the create, txn falls back in .catch()
sequelize.transaction(t => 
  Project.create(project, {
    include: [{
      model: User,
      as: 'Users',
    }],
    transaction: t,
  })
)
.catch(e => console.log('the txn failed because', e));
Sign up to request clarification or add additional context in comments.

4 Comments

Thank You for the response). It saves all data as expected, but log shows several "Executing" lines with the same key: Executing (some_key): START TRANSACTION; Executing (the_same_key): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; Executing (the_same-Key): INSERT INTO "user" ... RETURNING *; Executing (the_same-Key): ...other inserts... Executing (the_same-Key): COMMIT; Dose the same key show that everything happens in one query?
I doubt it, that's usually part of the trade-off with using an ORM.
And to clarify, by wrapping it in a transaction if any of the INSERTS fail, they will all be rolled back. It's also possible that multiple queries are sent to the server at one time rather than a back and forth, but performance wise I think it's negligible.
Ok, understand. I can not upwote your answer because of my reputation, but I'll mark it as answered.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.