Sequelize返回查询中的联接表。

11

我在我的MSQL表中有一个多对多的关系,涉及以下两个模型:

  • Venue - 代表一个场馆,可以拥有多个所有者(员工)
  • Employee - 代表可以是CEO或销售员工等的员工。

我正在使用设置关系,如下所示:

Employee > Venue 关系

 Employee.associate = function (models) { 
   models.Employee.belongsToMany(models.Venue, { through: 'EmployeeVenues' })
 }

关系场地 > 员工

 Venue.associate = function (models) {
    models.Venue.belongsToMany(models.Employee, { through: 'EmployeeVenues' })
 }
根据Sequelize文档,它将创建一个名为EmployeeVenues的新模型,其中包含等效的外键employee_id和venue_id。定义through是必需的。Sequelize以前会尝试自动生成名称,但这不总是导致最合乎逻辑的设置。这将添加方法getVenues、setVenues、addVenue、addUsers到Employee。此操作能够正常运行,当我启动我的Sequelize时,它会创建一个名为EmpoyeeVenues的新表,具有正确的复合键作为外键。然而,当我查询getVenues时,它不返回预期的输出。相反,它返回了关联表的值,而我不想要。获取id等于1的员工所属的所有场馆的查询:
router.get('/api/v1/users/:employee_id/venues', (request, response) => {
  var employeeId = request.params.employee_id;

  models.Employee.findOne({
    where: {id: employeeId}
  }).then((employee) => {

    if(!employee) { return response.status(400).send("Employee doesnt have a venue registered yet.")}
    var venues = employee.getVenues().then((venues) => {
    response.status(200).send(venues);
  })
})
});

响应结果


[
    {
        "id": 1,
        "capacity": "11",
        "venue_name": "Club Fix",
        "venue_description": "Club in Tilburg",
        "EmployeeVenues": {
            "employee_id": 1,
            "venue_id": 1
        }
    },
    {
        "id": 2,
        "capacity": "400",
        "venue_name": "Club Vie",
        "venue_description": "Club in Rotterdam",
        "EmployeeVenues": {
            "employee_id": 1,
            "venue_id": 2
        }
    }
]

问题

为什么Sequelize提供的查询中包含EmployeeVenues?如何防止EmployeeVenues被包含在响应中?


更新

根据Sequelize GitHub页面上于2014年发布的一个问题,有一个解决方案可行。

https://github.com/sequelize/sequelize/issues/2143

    User.find({
    where: {id: userId}, attributes: userFields,
    include: [
      {model: db.Role, attributes: roleFields, through: {attributes: []}}
    ]
});

但是它与Sequelize文档中的记录版本不匹配,该文档应该是最新的。


User.findAll({
  include: [{
    model: Project,
    through: {
      attributes: ['createdAt', 'startedAt', 'finishedAt'],
      where: {completed: true}
    }
  }]
});

甚至可以在参考文档中简单说明:


user.getPictures() // gets you all pictures
3个回答

10

更新

根据2014年在Sequelize的github页面上发布的一个问题,有一个可行的解决方案。

https://github.com/sequelize/sequelize/issues/2143

    User.find({
    where: {id: userId}, attributes: userFields,
    include: [
      {model: db.Role, attributes: roleFields, through: {attributes: []}}
    ]
});
但它与Sequelize文档中的记录版本不匹配,该文档应该是最新的。
User.findAll({
  include: [{
    model: Project,
    through: {
      attributes: ['createdAt', 'startedAt', 'finishedAt'],
      where: {completed: true}
    }
  }]
});

甚至可以在参考文档中简单说明:


user.getPictures() // gets you all pictures

5
我认为给出的答案忽略了一个重要的事情-需要将所需的属性保存在包含的模型中,这里是Project。issue在github上有最终答案,但仍不是我期望的完整答案。
我们需要在模型级别重新指定属性,然后将联接表属性设置为none。
User.findAll({
  include: [{
    model: Project,

    through: 'JoinTableAliasName' /// only if exist/needed
    as: 'modelAssociationAlias' // only if exist/needed

    // attributes needed from Project table
    attributes: ['createdAt', 'startedAt', 'finishedAt'],

    through: { // through again doesn't create any issue
      attributes: [], // this helps removing the join table in returned data
      where: {completed: true}
    }
  }]
});

我很难找到一个好的例子。虽然它并不完全是我所做的,但它给了我足够的信息来弄清楚我需要做什么(所以感谢额外的评论)。 - ScottS
如果您想使用关联 mixin 指定通过表属性,您需要在 mixin 方法内传递 {joinTableAttributes: ['fields']}。 - Eziz Hudayberdiyev

1

这种方法在我的情况下完美地运作:

user.getPictures({joinTableAttributes: []}) 

Foo.belongsToMany


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接