Sequelize在belongsToMany中保存数据创建表并从中读取(最后的解决方案)

时间:2016-08-05 14:30:14

标签: angularjs sql-server node.js express sequelize.js

我正在使用我的Backend Node.js,Express.js和Sequelize来连接数据库。 我有一个n:m任务和键之间的关系。 schema

任务和密钥由我和TaskKey通过Sequelize创建:

后端

    // Tasks n:m Keys
    db.DictKey.belongsToMany(db.Task, { through: 'TaskKeys' , foreignKey:'key_id'});
    db.Task.belongsToMany(db.DictKey, { through: 'TaskKeys' , foreignKey: 'task_id'});

现在,如果我在

上创建一个新任务

前端

$scope.create = () => {
    this.$http.post('/api/tasks', {
        user_id: $scope.selectUser,
        lang_id: $scope.selectLang,
        name: $scope.newTask
    });
}

我希望使用该请求发送用户选择的所有密钥的数组。

在后端,它应该为TaskKeys添加一个条目,用于发送的每个DictKey的新任务。 例如

表格任务:

ID | some values
1  | some values | this is the new task created

发送数组中的密钥[2,5,6]

TaskKey /在同一时刻在此表中创建从属密钥

TaskID | KeyID
1      | 2
1      | 5
1      | 6

我怎样才能做到这一点?

之后我想展示一个任务。 以前的例子。 获取id = 1的任务 ng-repeat所有数据,并且由于Table TaskKey而获得所有密钥。

我找不到一个解释这个问题的示例,我目前唯一的解决方案就是$http.post(taskkey)的前端,表foreach中的每个键都有一个TaskKey 。但是后来在Live System中会有超过1000个密钥,所以这不是一个可接受的解决方案。 对于后端有一个很好的解决方案吗?

EDIT1:

...    working fine
$scope.create = () => {
            this.$http.post('/api/tasks', {
              task:{
              user_id: $scope.selectUser,
              lang_id: $scope.selectLang,
              name: $scope.newTask
            },
            keys:[1,2,3,4,5]
          });
    ...
 ... 
// Creates a new Task in the DB
export function create(req, res) {
  return Task.create(req.body.task)
  .then(function(task){
    return task.addTaskKeys(req.body.keys);//throws 500error
    //console.log(req.body.keys);//working fine getting the Keys
  })
    .then(respondWithResult(res, 201))
    .catch(handleError(res));
}
...

阅读文档belongsToManyDoc并没有多大帮助,因为没有示例或详细说明。 我尝试了几件事:

  • addTask / addTasks / addTaskKeys / addKey,如在解释为添加关联的文档中所述
  • 用于创建关联的createTask / createKey / createTaskKeys

在我的后端,我没有TaskKeys的任何函数只用于任务和键。但据我所知,我不需要任何TaskKeys因为

 // Tasks n:m Keys
    db.DictKey.belongsToMany(db.Task, { through: 'TaskKeys' , foreignKey:'key_id'});
    db.Task.belongsToMany(db.DictKey, { through: 'TaskKeys' , foreignKey: 'task_id'});  

创建中间表,任务和密钥之间存在关联。所以通常add / create应该正常工作,它应该在TaskKeys中添加实例。

 export function create(req, res) {
      return Task.create(req.body.task)
      .then(function(task){
        return task.addTaskKeys(req.body.keys);//throws 500error

使用task.addTaskKeys添加与刚刚创建的Task =>的关联task_id

使用req.body.keys为他提供Keys => key_id
如果我将示例从Doc更改为minde DB:

... example
    Project.create({ id: 11 }).then(function (project) {
      user.addProjects([project, 12]);
    });
... mine
return Task.create(req.body.task)
  .then(function(task){
    return DictKey.addTasks([task,{key_id : 1}]);//still error
  })//DictKey.addTask(task,1); still error

阅读BelongsToMany协会并引用它:

  

user.addProject(项目,{状态:'已启动'})   默认情况下,代码会将projectId和userId添加到UserProjects表

尝试使用关联进行创建:

  

http://sequelize.readthedocs.io/en/latest/docs/associations/#creating-elements-of-a-hasmany-or-belongstomany-association   抱歉,不允许发布更多1个链接。

export function create(req, res) {
  return Task.create({
    name: req.body.task.name,
    user_id: req.body.task.user_id,
    lang_id: req.body.task.lang_id,
    key_id:[req.body.keys]
  },{
    include: [DictKey]
  })

没有错误但只创建任务而不是TaskKeys .... 那么整个时间我做错了什么?

EDIT2: 对于测试,我在MsSql中由Myself在Table TaskKeys中插入了数据。 使用SqlQuery

的TaskKey / Self Created Datas
TaskID | KeyID
1      | 1
1      | 2
1      | 3
2      | 4
2      | 5

前端

获取
this.$http.get('/api/tasks/' +2 )
            .then(response => {
              this.Tasks = response.data;
              console.log(this.Tasks);
            });

后端

// Gets a single Task from the DB
export function show(req, res) {
  return Task.findAll({
    where: {
      _id: req.params.id
    },
    include: [{
      model: DictKey
    }]
  })
    .then(handleEntityNotFound(res))
    .then(respondWithResult(res))
    .catch(handleError(res));
}

ConsoleOutput:

[Object]
Object
_id:2 // the searched TaskId= 2 => right
dict_Keys:Array[2] // the Dependant 2 KeyIds => right

因此创建的表工作正常。 问题现在只是为什么通过Backend添加addKey无法通过执行与示例相同的工作。 尝试使用示例检查关联:

// Creates a new Task in the DB
export function create(req, res) {
  Task.create({
  name: req.body.task.name,
  user_id: req.body.task.user_id,
  lang_id: req.body.task.lang_id
}).then(function(task) {
    return DictKey.create({ name:req.body.task.name,notice:req.body.task.name, user_id:req.body.task.user_id })
    .then(function(key) {
      return task.hasDictKey(key).then(function(result) {
        // result would be false
        return task.addDictKey(key).then(function() {
          return task.hasDictKey(key).then(function(result) {
            // result would be true
          })
        })
      })
    })
  })

抛出task.hasDictKey不是函数

db.Task.create({
  name: 'test',
  user_id: 266,
  lang_id: 9,
  key_id:[1,2]
},{
  include: [db.DictKey]
})

抛出dict_Keys与Task无关 那么这意味着他们没有连接在一起? BUt读取数据和在数据库中插入数据是否有效?

现在添加Sequelize的例子:

var Usert = db.sequelize.define('usert', {})
var Project = db.sequelize.define('project', {})
var UserProjects = db.sequelize.define('userProjects', {
    status: Sequelize.STRING
})

Usert.belongsToMany(Project, { through: UserProjects })
Project.belongsToMany(Usert, { through: UserProjects })
Usert.addProject(Project, { status: 'started' })//addProject is not a Function // for real ? now not even their own is not working? :/

答案
通过阅读我想到的文档

// Tasks n:m Keys
db.DictKey.belongsToMany(db.Task, { through: TaskKeys , foreignKey:'key_id',otherKey:'task_id'});
db.Task.belongsToMany(db.DictKey, { through: TaskKeys , foreignKey: 'task_id',otherKey: 'key_id'});

它会自动为DictKey生成add / set / get / create任务,并为Task添加/ set / get / create DictKey。

但是

  

命名策略

     

默认情况下,sequelize将使用模型名称(传递给的名称)   sequelize.define)用于确定模型的名称   关联。

表示它按表格模型的名称添加函数define('dict_Keys'... 所以将add / set / get / Dict_Key添加到Task。 这是问题,因为我使用addDictkey而不是addDict_Key。 我希望它能帮助未来的其他人

2 个答案:

答案 0 :(得分:2)

前端:要从前端获取数据,只需将数组包含为您发布的data的属性。您可能还希望将任务特定属性包装在它们自己的对象中:

this.$http.post('/api/tasks', {
    task: {
        user_id: $scope.selectUser,
        lang_id: $scope.selectLang,
        name: $scope.newTask
    },
    keys: [ 2, 5, 6 ]
});

后端:Sequelize和其他ORM会尝试为您提供使用您定义的关系的工具。使用它们。您已经在使用belongsToMany,因此您只需要执行下一步,即使用创建的Task对象在m:n中创建TaskKeys条目:

...
return Task.create(req.body.task)
    .then(function(task) {
        return task.addProjects(req.body.keys);
    })
    .then(respondWithResult(res, 201))
    .catch(handleError(res));
...

至于使用密钥获取任务,只需使用include选项:

...
return Task.findById(req.params.id, {
    include: [ { model: db.DictKey } ]
})
...

答案 1 :(得分:0)

foreignKey在关系的两边应该相同,设置另一个关键字使用otherKey选项。