You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Node.js的Sequelize ORM获取10个唯一用户及关联分类

问题根源

你的LIMIT是作用在用户-分类关联后的所有行上,而非唯一用户本身。当一个用户关联多个分类时,会生成多行结果,导致最终返回的唯一用户数量不足10个。

解决方案

1. 直接调整SQL语句

先通过子查询筛选出符合条件的10个唯一用户,再关联分类表获取这些用户的所有分类:

SELECT
  `User`.*,
  `userCategories`.`id` AS `userCategories.id`,
  `userCategories`.`category_id` AS `userCategories.categoryId`
FROM
  (
    -- 子查询先拿到10个符合条件的唯一用户ID
    SELECT `id`, `updatedAt`
    FROM `users`
    WHERE
      `deleted_at` IS NULL
      AND `country_id` IN (1)
      AND `is_blocked` = false
      -- 确保用户关联了指定分类
      AND EXISTS (
        SELECT 1 FROM `user_categories`
        WHERE `user_id` = `users`.`id`
          AND `deleted_at` IS NULL
          AND `category_id` IN ('129', '203')
      )
    ORDER BY `updatedAt` DESC
    LIMIT 10 OFFSET 1
  ) AS `FilteredUsers`
  -- 关联主用户表获取完整用户信息
  JOIN `users` AS `User` ON `FilteredUsers`.`id` = `User`.`id`
  -- 关联分类表获取该用户的所有分类
  LEFT OUTER JOIN `user_categories` AS `userCategories` 
    ON `User`.`id` = `userCategories`.`user_id`
    AND `userCategories`.`deleted_at` IS NULL
ORDER BY `User`.`updatedAt` DESC;

2. 使用Sequelize ORM实现

方式一:分两步查询(清晰直观)

先筛选出目标用户ID,再查询这些用户及其所有分类:

const { Op, Sequelize } = require('sequelize');
// 假设User和UserCategory是已定义的模型,且关联名为userCategories

// 第一步:获取符合条件的10个用户ID
const filteredUsers = await User.findAll({
  attributes: ['id', 'updatedAt'],
  where: {
    deleted_at: null,
    country_id: [1],
    is_blocked: false,
    // 用EXISTS确保用户关联了指定分类
    [Op.and]: [
      Sequelize.literal(`EXISTS (
        SELECT 1 FROM user_categories
        WHERE user_id = users.id
          AND deleted_at IS NULL
          AND category_id IN ('129', '203')
      )`)
    ]
  },
  order: [['updatedAt', 'DESC']],
  limit: 10,
  offset: 1
});

const userIds = filteredUsers.map(user => user.id);

// 第二步:查询这些用户的完整信息及所有分类
const result = await User.findAll({
  where: { id: userIds },
  include: [{
    model: UserCategory,
    as: 'userCategories',
    where: { deleted_at: null },
    required: false // 保留左连接,即使用户后续没有分类也能返回(可选)
  }],
  order: [['updatedAt', 'DESC']]
});

方式二:单查询嵌套子查询(更简洁)

直接在WHERE条件中用子查询限定用户ID范围:

const { Op, Sequelize } = require('sequelize');

const result = await User.findAll({
  include: [{
    model: UserCategory,
    as: 'userCategories',
    where: { deleted_at: null },
    required: false
  }],
  where: {
    deleted_at: null,
    country_id: [1],
    is_blocked: false,
    id: {
      [Op.in]: Sequelize.literal(`(
        SELECT id FROM users
        WHERE deleted_at IS NULL
          AND country_id IN (1)
          AND is_blocked = false
          AND EXISTS (
            SELECT 1 FROM user_categories
            WHERE user_id = users.id
              AND deleted_at IS NULL
              AND category_id IN ('129', '203')
          )
        ORDER BY updatedAt DESC
        LIMIT 10 OFFSET 1
      )`)
    }
  },
  order: [['updatedAt', 'DESC']]
});
注意事项
  • 原SQL中WHERE子句存在语法错误:AND userCategories.category_id IN ('129', '203')前面多了一个多余的AND,需要删除才能正常执行。
  • 如果不需要保留没有分类的用户,可以将required: false改为required: true(内连接),但子查询已经确保用户关联了指定分类,所以两种设置差异不大。

内容的提问来源于stack exchange,提问作者Faizan Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:27:41