【问题标题】:Sequelize: Query same join table with different conditionsSequelize:用不同的条件查询同一个连接表
【发布时间】:2017-06-12 12:40:52
【问题描述】:

我有两个模型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 },
    }),
})

但是这也不起作用,因为它包含相同模型的重复。

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

【问题讨论】:

    标签: javascript node.js postgresql sequelize.js


    【解决方案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]},
    });
    

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

    【讨论】:

    • 有用的替代品,这也是我需要做joins时使用的,但仍然希望看到“续集”方式的示例。
    • 是的,很高兴在 Sequelize 中看到它......但这非常适合我的应用程序。谢谢:)
    • 我只需要添加一件事,因为数组需要包含 exact 联系人 ID 列表:HAVING array_agg(thread_contacts.contact_id) @> ARRAY[:contactIds] AND array_agg(thread_contacts.contact_id) <@ ARRAY[:contactIds];
    • 很好的解决方案!请注意,您不必为此使用完全原始的查询。这可以写成:Thread.findAll({ include: { model: ThreadContact, required: true }, group: ['Thread.id'], having: sequelize.where(sequelize.fn('array_agg', 'ThreadContact.contactId'), '@>', contactIds) }),或者类似的东西。一般来说,限制查询的原始程度有助于提高安全性和可维护性。
    猜你喜欢
    • 2016-07-22
    • 2015-07-05
    • 2023-01-10
    • 2014-01-05
    • 2023-03-06
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多