【问题标题】:Sequelize Many to Many - How to create a new record and update join tableSequelize Many to Many - 如何创建新记录和更新连接表
【发布时间】:2015-05-03 12:20:49
【问题描述】:

我正在使用 node、express 和 sequelize 构建一个简单的数据库。我已经创建了模型,并且 sequelize 在我的数据库中创建了表。

我有模型用户和城市,具有多对多关系。 Sequelize 使用 UserId 和 CityId 创建了表 Users、Cities 和连接表 CitiesUsers:。

我的问题是,当我创建新用户时,如何更新该联接表? CityId 属性在创建时被忽略。

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

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

    user.save();

【问题讨论】:

  • 请注意,对于多对多关系,您需要将belongsToMany 用于关联:City.belongsToMany(User, { through: UserCity })

标签: javascript mysql sequelize.js


【解决方案1】:

在深入研究文档之后,我相信我已经找到了答案。

当创建多对多关系时,sequelize 会为每个模型创建 get、set 和 add 方法。

从文档中假设模型 User 和 Project 具有多对多: http://docs.sequelizejs.com/en/latest/docs/associations/#belongs-to-many-associations

这会将方法 getUsers、setUsers、addUsers 添加到 Project 和 getProjects、setProjects 和 addProject 到用户。

因此,在我的情况下,我执行了以下操作,其中“城市”是从 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]);
  });      
});

【讨论】:

    【解决方案2】:

    一旦创建了 City 和 User 模型,您就可以创建用作连接表的模型的新实例。

    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 })
    
    
    const user = await User.create()
    const city = await City.create()
    
    const userCity = await UserCity.create({
      userId: user.userId,
      cityId: city.cityId,
    })
    

    【讨论】:

      【解决方案3】:

      只是为了补充这个线程中的许多优秀答案,我通常发现当我有一个实体引用另一个实体时,如果(且仅当)它不存在时,我想创建被引用的实体。为此,我喜欢使用findOrCreate()

      假设您正在存储文章,每篇文章可以有任意数量的标签。您通常想要做的是:

      1. 遍历所有需要的标签,并检查它们是否存在。如果它们不存在,请创建它们。
      2. 找到或创建所有标签后,创建您的文章。
      3. 创建文章后,将其链接到您在第 1 步中查找(或创建)的标签。

      对我来说,这最终看起来像:

      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]));
        })
      })
      

      【讨论】:

      【解决方案4】:

      来自文档 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-05
        • 1970-01-01
        • 2020-07-01
        • 1970-01-01
        • 2019-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多