Sequelize:查询具有不同条件的相同连接表

时间:2017-01-26 21:56:35

标签: javascript node.js postgresql sequelize.js

我有两个模型ContactThread,在关联表ThreadContacts中表示多对多关系。

我需要写一个查询查找与联系人的确切列表有关联的主题。例如,我可能有一个contact_id的列表 [1,2,3,4],我需要找到与这4个联系人相关联的Thread

我尝试在findAll查询中包含Contact

Thread.findOne({
    include: [{
        model: Contact,
        where: { id: $in: [1, 2, 3, 4] },
    }],
})

当然这不起作用,因为它会返回一个ThreadContact与4个ID中的任何一个的线程。

我需要这样的东西:

Thread.findAll({
    include: contactIds.map(id => ({
        model: Contact,
        where: { id },
    }),
})

然而,这也不起作用,因为它包含相同型号的副本。

我有什么选择?我很难找到解决方案。

1 个答案:

答案 0 :(得分:1)

在sequelize中编写更复杂的连接查询时,我通常最终使用raw query interface。它看起来有点复杂,但希望它有道理:

  • 选择线程并使用ThreadContact表连接
  • 分组Thread.id
  • 使用联系人ID上的array_agg汇总群组。所以我们现在为每个线程都有一个所有相关联系人的数组。
  • 然后过滤到汇总数组所包含的位置' (由@>表示)您输入的过滤器。见postgres array functions

结果将是与至少4个联系人相关联的所有主题。

sequelize.query(`
  SELECT Thread.*
  FROM Thread
  INNER JOIN ThreadContact
    ON Thread.id = ThreadContact.threadId
  GROUP BY Thread.id
  HAVING array_agg(ThreadContact.contactId) @> ARRAY[:contactIds];
`, {
  model: Thread,
  mapToModel: true,
  type: sequelize.QueryTypes.SELECT,
  replacements: {contactIds: [1, 2, 3, 4]},
});

另请注意,根据模型的定义,列名可能不正确,我只是对它们的外观做了一些假设。