使用两个表续展嵌套关联

时间:2016-12-06 03:31:48

标签: node.js associations sequelize.js

我有一个场景,我试图用两个相互关联的表(引用和用户)查询父表(文档),这些表彼此没有关系,但确实与父表有关系。在SQL中,此查询看起来像这样并正确输出我要查找的数据:

select *
from `document`
left join `user`
on `document`.`user_id` = `user`.`user_id`
left join `reference`
on `document`.`reference_id` = `reference`.`reference_id`
where `user`.`organization_id` = 1;

但是,嵌套的关联必须按层次顺序关联才能使查询起作用。由于嵌套关联彼此不相关,因此会出现关联错误。我怎样才能避免这个错误? required: false会对此产生影响吗?

models.Document.findAll({
  order: 'documentDate DESC',
  include: [{
    model: models.User,
    where: { organizationId: req.user.organizationId },
    include: [{
      model: models.Reference,
    }]
  }],
})

错误

  

未处理拒绝错误:引用与用户无关!

协会

Document

associate: function(db) {
  Document.belongsTo(db.User, {foreignKey: 'user_id'}),
    Document.belongsTo(db.Reference, { foreignKey: 'reference_id'});;
}

Reference

associate: function(db){
  Reference.hasMany(db.Document, { foreignKey: 'reference_id' });
}

我应该直接链接查询吗?

3 个答案:

答案 0 :(得分:2)

如果要复制查询(尽可能接近),请使用以下查询。请注意,用户where上的include仅用于删除Document.user_idUser.organization_id不匹配的Document匹配,但User.organization_id仍会被退回如果您要省略required: true不匹配的文档,请使用User <- Document -> Reference

models.Document.findAll({ // this is an array of includes, don't nest them include: [{ model: models.User, where: { organization_id: req.user.organization_id }, // <-- underscored HERE required: true, // <-- JOIN to only return Documents where there is a matching User }, { model: models.Reference, required: false, // <-- LEFT JOIN, return rows even if there is no match }], order: [['document_date', 'DESC']], // <-- underscored HERE, plus use correct format });

@echo off
set arg1=%1
shift
javac -cp . %arg1%.java
java %arg1%
pause

答案 1 :(得分:0)

错误表明User模型未与Reference模型相关联,但您的描述中只有DocumentReference模型的定义。您正在使用include选项在查询中加入这些表,因此您必须确保它们已关联。您在技术上也不需要此处foreignKey,您指定的是默认值。

添加Reference->User关联

associate: function(db) {
  // belongsTo()? maybe another relationship depending on your data model
  Reference.belongsTo(db.User, {foreignKey: 'user_id'});

  Reference.hasMany(db.Document, { foreignKey: 'reference_id' });
}

您也可能在模型定义中设置了underscored: true,因此您的查询应该反映这一点。此外,如果您要执行LEFT JOIN,则需要在required: false上指定include,否则它是常规JOIN,并且您只会返回包含匹配项的行include d模型。您还使用了错误的order格式,它应该是一个值数组,要按model.document_date DESC排序,您应该使用order: [['document_date', 'DESC']]

正确的查询参数

models.Document.findAll({
  order: [['document_date', 'DESC']], // <-- underscored HERE, plus use correct format
  include: [{
    model: models.User,
    where: { organization_id: req.user.organization_id }, // <-- underscored HERE
    required: false, // <-- LEFT JOIN
    include: [{
      model: models.Reference,
      required: false, // <-- LEFT JOIN
    }]
  }],
});

如果您仍然遇到问题,请尝试通过在Sequelize连接中设置logging: console.log启用日志记录,该连接将显示您在控制台中运行的所有查询。

答案 2 :(得分:0)

在我看来,您的问题可能是关联,尝试链接回文档上的主键而不是列&#39; user_id&#39;和&#39; reference_id&#39;。你没有发布表属性,所以我可能已经理解了这个错误。

文件上的关联是可以的。

文档

associate: function(db) {
  Document.belongsTo(db.User, {foreignKey: 'user_id'}),  //key in documents
  Document.belongsTo(db.Reference, { foreignKey: 'reference_id'}); //key in documents
}

用户

associate: function(db) {
  User.belongsTo(db.Document, {
    foreignKey: 'id',    //Key in User
    targetKey: 'user_id' //Key in Documents
  }),
}

参考

associate: function(db) {
  Reference.belongsTo(db.Document, {
      foreignKey: 'id',         //Key in reference
      targetKey: 'reference_id' //Key in Documents
  }),
}

另外

对于debbuging,请考虑使用日志记录,以便查看查询。

var sequelize = new Sequelize('database', 'username', 'password', {
    logging: console.log
    logging: function (str) {
        // do your own logging
    }
});