findOrCreate with include
Asked Answered
M

2

8

I want to create a Tournament (if not exists), and a Match (if not exists) associated to the Tournament.

let [match, created] = await Match.findOrCreate( {
  where: {scoreHome: 97, Tournament: {name: "USA South Men's Basketball"}}, 
  include: [Tournament]
})

If the tournament 'USA South Men's Basketball' is already in the db (let's say with id 1), then the match should be created with TournamentId: 1. If there is already a match in the db with {scoreHome: 97 and TournamentId: 1}, then no match should be created.

  let Match = sequelize.define('Match', {
    scoreHome: DataTypes.INTEGER,
    //...
  })

  Match.associate = models => {
    Match.belongsTo(models.Tournament)
  }

EDIT Here is the error:

[Error: Invalid value [object Object]]

This works fine

let match = await Match.create({
    scoreHome: 97, Tournament: {name: "USA South Men's Basketball"}
  },{include: [Tournament]}
})
Manana answered 6/8, 2017 at 10:0 Comment(0)
M
2

I am not sure sequelize will allow this "deep findOrCreate". But you can achieve the wanted effect using two queries, and the sequelize transaction to make sure the two are linked together:

const t = await sequelize.transaction();

try {
  const [tournament] = await Tournament.findOrCreate({
    where: {name: "USA South Men's Basketball"},
    { transaction: t }
  })
  const [match] = await Match.findOrCreate({
    where: {scoreHome: 97, tournamentId: tournament.id},
    { transaction: t }
  })
  t.commit()
} catch(err) {
  t.rollback()
}

It is a bit more verbose, but with this you are sure of what you do, and it is also (personal opinion) more readable for another dev reading that after you.

Mcadoo answered 20/8, 2020 at 9:29 Comment(0)
U
2

The issue you're encountering is because findOrCreate does not directly handle nested relations in the same way create does with include. You can try this instead:

// First, find or create the Tournament
let [tournament] = await Tournament.findOrCreate({
  where: { name: "USA South Men's Basketball" }
});

// Now, find or create the Match using the Tournament's ID
let [match, created] = await Match.findOrCreate({
  where: { scoreHome: 97, TournamentId: tournament.id }
});
Upgrade answered 14/10 at 13:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.