web-dev-qa-db-fra.com

Sequelize Many to Many - Comment créer un nouvel enregistrement et mettre à jour la table de jointure

Je construis une base de données simple avec nœud, express et séquelle. J'ai créé mes modèles et j'ai ensuite créé les tables dans ma base de données.

J'ai les modèles User et City, avec une relation plusieurs à plusieurs. Sequelize a créé les tables Users, Cities et une table Join CitiesUsers: avec UserId et CityId.

Ma question est quand je crée un nouvel utilisateur comment mettre à jour cette table de jointure? La propriété CityId est ignorée lors de la création.

   //Models use 
   //City.hasMany(User);
   //User.hasMany(City);

   var user = User.build({
      first_name: 'John',
      last_name: 'Doe',
      CityId: 5
    });

    user.save();
15
RickTakes

Après avoir approfondi la documentation, je pense avoir trouvé la réponse.

Lorsque vous créez une relation plusieurs à plusieurs, la séquelle crée des méthodes get, set et add pour chaque modèle.

De la documentation en supposant des modèles utilisateur et projet avec plusieurs à plusieurs: http://docs.sequelizejs.com/en/latest/docs/associations/#belongs-to-many-associations

Cela ajoutera les méthodes getUsers, setUsers, addUsers à Project et getProjects, setProjects et addProject à User.

Donc, dans mon cas, j'ai fait ce qui suit où "ville" est un modèle City spécifique renvoyé par City.find ...

//user.setCities([city]);

models.User.find({ where: {first_name: 'john'} }).on('success', function(user) {
  models.City.find({where: {id: 10}}).on('success', function(city){
    user.setCities([city]);
  });      
});
8
RickTakes

Vous pouvez créer une nouvelle instance du modèle utilisé comme table de jointure une fois que les modèles Ville et Utilisateur ont été créés.

const User = sequelize.define('user')
const City = sequelize.define('city')
const UserCity = sequelize.define('user_city')

User.belongsToMany(City, { through: UserCity })
City.belongsToMany(User, { through: UserCity })

Promise.all([User.create(), City.create()])
    .then(([user, city]) => UserCity.create({userId: user.id, cityId: city.id}))
6
Danny Sullivan

Juste pour ajouter aux nombreuses excellentes réponses de ce fil, je trouve généralement que lorsque j'ai une entité en référençant une autre, je veux créer l'entité référencée si (et seulement si) elle n'existe pas déjà. Pour cela, j'aime utiliser findOrCreate() .

Imaginez donc que vous stockiez des articles et que chaque article puisse avoir un nombre quelconque de balises. Ce que vous voudriez généralement faire, c'est:

  1. Parcourez toutes les balises souhaitées et vérifiez si elles existent. Créez-les s'ils n'existent pas déjà.
  2. Une fois toutes les balises trouvées ou créées, créez votre article.
  3. Une fois votre article créé, liez-le aux balises que vous avez recherchées (ou créées) à l'étape 1.

Pour moi, cela ressemble à:

const { article, tags } = model.import("./model/article");

let tagging = [
  tags.findOrCreate({where: {title: "big"}}),
  tags.findOrCreate({where: {title: "small"}}),
  tags.findOrCreate({where: {title: "medium"}}),
  tags.findOrCreate({where: {title: "xsmall"}})
];

Promise.all(tagging).then((articleTags)=> {
  article.create({
    title: "Foo",
    body: "Bar"    
  }).then((articleInstance) => {
    articleInstance.setTags(articleTags.map((articleTag) => articleTag[0]));
  })
})
1
Matt Korostoff

Depuis The docs v3:

// Either by adding a property with the name of the join table model to the object, before creating the association
project.UserProjects = {
  status: 'active'
}
u.addProject(project)

// Or by providing a second argument when adding the association, containing the data that should go in the join table
u.addProject(project, { status: 'active' })


// When associating multiple objects, you can combine the two options above. In this case the second argument
// will be treated as a defaults object, that will be used if no data is provided
project1.UserProjects = {
    status: 'inactive'
}

u.setProjects([project1, project2], { status: 'active' })
// The code above will record inactive for project one, and active for project two in the join table
1
Yassine Mokni