简体   繁体   English

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

[英]Sequelize: Query same join table with different conditions

I have two models Contact and Thread with a many to many relationship represented across a join table ThreadContacts . 我有两个模型ContactThread ,在连接表ThreadContacts表示多对多的关系。

I need to write a query to find a Thread which has associations with an exact list of Contacts . 我需要编写一个查询来查找一个与一个确切的联系人列表有关联的Thread For example, I might have a list of contact_id 's [1,2,3,4], and I need to find a Thread that is associated with these exact 4 contacts. 例如,我可能有一个contact_id的列表[1,2,3,4],我需要找到一个与这4个联系人关联的Thread

I have tried including Contact on a findAll query: 我试过在findAll查询中包含Contact

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

Of course this doesn't work because it'll return a thread that has a ThreadContact with any of the 4 ids. 当然这不起作用,因为它将返回一个ThreadContact与4个ID中的任何一个的线程。

I need something like this: 我需要这样的东西:

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

However this also doesn't work because it is including duplicates of the same model. 但是,这也不起作用,因为它包含相同模型的重复项。

What are my options here? 我有什么选择? I'm having a difficult time finding a solution for this. 我很难找到解决方案。

When writing more complicated join queries in sequelize, I usually end up using the raw query interface . 在sequelize中编写更复杂的连接查询时,我通常最终使用原始查询界面 It looks a bit complicated, but hopefully it makes sense: 它看起来有点复杂,但希望它有意义:

  • Select the Threads and join with the ThreadContact table 选择Threads并使用ThreadContact表连接
  • Group by Thread.id Thread.id分组
  • Aggregate the group using array_agg on the contact ids. 使用联系人ID上的array_agg聚合组。 So we now have an array of all associated contacts for each thread. 所以我们现在有一个每个线程的所有相关联系人的数组。
  • Then filter to where the aggregated array 'contains' (as represented by @> ) your inputted filter. 然后过滤到汇总数组'包含'(由@>表示)输入过滤器的位置。 See postgres array functions . 参见postgres数组函数

The result will be all Threads which are associated with at least those 4 contacts. 结果将是与至少这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]},
});

Also note that the column names may be incorrect from how your model is defined, I just made some assumptions on how they would look. 另请注意,列名称可能与您的模型定义方式不一致,我只是对它们的外观做了一些假设。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM