Javascript Sequelize Many to Many - 如何创建新记录并更新连接表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28821812/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:28:23  来源:igfitidea点击:

Sequelize Many to Many - How to create a new record and update join table

javascriptmysqlsequelize.js

提问by RickTakes

I'm building a simple database with node, express and sequelize. I have created my models, and sequelize created the tables in my database.

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

I have the models User and City, with a many to many relationship. Sequelize created the tables Users, Cities and a join table CitiesUsers: with UserId and CityId.

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

My question is when I create a new user how do I update that join table? The CityId property gets ignored on create.

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

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

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

    user.save();

回答by RickTakes

After digging further into the documentation, I believe I've found the answer.

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

When creating a many to many relationship sequelize creates get, set and add methods to each model.

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

From the docs assuming models User and Project with many to many: http://docs.sequelizejs.com/en/latest/docs/associations/#belongs-to-many-associations

从文档假设模型用户和项目多对多:http: //docs.sequelizejs.com/en/latest/docs/associations/#belongs-to-many-associations

This will add methods getUsers, setUsers, addUsers to Project, and getProjects, setProjects and addProject to User.

这会将方法 getUsers、setUsers、addUsers 添加到 Project,并将 getProjects、setProjects 和 addProject 添加到 User。

So in my case I did the following where "city" is a specific City model returned from City.find...

所以就我而言,我做了以下操作,其中“城市”是从 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]);
  });      
});

回答by Danny Sullivan

You can create a new instance of the model used as the join table once both City and User models have been created.

一旦创建了 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 })

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

回答by Matt Korostoff

Just to add on to the many excellent answers in this thread, I find generally that when I have one entity referencing another, I want to create the referenced entity if (and only if) it does not already exist. For this I like to use findOrCreate().

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

So imagine you were storing articles, and each article could have any number of tags. What you'd typically want to do is:

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

  1. Iterate through all the desired tags, and check if they exist. Create them if they don't already exist.
  2. Once all the tags have been found or created, create your article.
  3. Once your article has been created, link it to the tags you looked up (or created) in step 1.
  1. 遍历所有需要的标签,并检查它们是否存在。如果它们不存在,则创建它们。
  2. 找到或创建所有标签后,创建您的文章。
  3. 创建文章后,将其链接到您在步骤 1 中查找(或创建)的标签。

For me, this winds up looking like:

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

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

回答by Yassine Mokni

From The docs v3:

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