【问题标题】:Sequelize save Data in belongsToMany created Table and Read from it(Solution at the End)Sequelize将数据保存在belongsToMany创建的表中并从中读取(最后解决)
【发布时间】:2016-12-12 00:23:41
【问题描述】:

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

Tasks and Keys 是我和 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
    });
}

我想与该请求一起发送用户选择的所有键的数组。

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

表任务:

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 all data 并通过 Table TaskKey 获取所有 Key。

我找不到一个示例来解释这一点,而我目前唯一的解决方案是在前端使用$http.post(taskkey),表TaskKey 中的每个键都有foreach。但后来在 Live System 中会有超过 1000 个键,所以这不是一个可接受的解决方案。 后端有没有好的解决方案?

编辑1:

...    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,因为有了

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

创建 Middle Table 存在 Tasks 和 Keys 之间的关联。所以通常添加/创建应该可以正常工作,它应该在 TaskKeys 中添加实例。

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

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

req.body.keys 给他 Keys =>key_id
如果我将示例从 Doc change 改为 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(project, { status: 'started' }) 默认情况下,代码会将 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]
  })

没有错误,但只创建任务而不是任务键...... 那么我一直在做错什么?

编辑2: 为了测试,我自己在 MsSql 中的 Table TaskKeys 中插入了数据。 TaskKey / 使用 SqlQuery 自行创建的数据

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

控制台输出:

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

所以创建的表工作正常。 现在的问题只是为什么通过与示例中的相同操作无法使用 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 未关联到任务 所以这意味着它们没有连接在一起? 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 并为 Task 生成 add/set/get/create DictKey。

但是

命名策略

默认情况下,sequelize 将使用模型名称(传递给 sequelize.define) 来确定模型在使用时的名称 协会。

意味着它通过您所在的表模型的名称添加函数define('dict_Keys'... 所以添加/设置/获取/ Dict_Key 到任务。 这就是问题所在,因为我使用的是 addDictkey 而不是 addDict_Key。 我希望它可以帮助未来的其他人

【问题讨论】:

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


    【解决方案1】:

    前端:要从前端获取数据,只需将数组作为您发布的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 对象在TaskKeys 中创建m:n 条目:

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

    【讨论】:

    • 感谢您的帮助。前端正在工作,但后端仍然存在问题。如果你可以检查 Edit1 ?
    • 当您收到return task.addTaskKeys(req.body.keys); 的 500 错误时,控制台在服务器上显示什么?
    • Console.log: ...先创建 Task.create 然后再进行 taskadd POST /api/tasks 500 57.938 ms - 2 BrwoserConsole 日志:POST http://localhost:9000/api/tasks 500 (Internal Server Error) 我尝试使用硬编码值,例如 addTask(1);//1 是肯定的100% 存在于 Key Table 同样的错误
    • 能否在启动服务器之前将DEBUG 环境变量设置为*,然后重试?那应该提供更多信息......就像DEBUG=* node server.js
    • DEBUG=express:* node index.js,来自 Express Docs at Debuging。没有改变太多的输出。但是将Task.create 注释掉并且只做return task.addKeys(1) 给出错误无法读取未定义的addTask 的属性?
    【解决方案2】:

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

    【讨论】:

    • // 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'}); 中添加otherKey 未能解决问题。与之前的问题一样
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    相关资源
    最近更新 更多