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

TypeORM关联查询:过滤主表时如何保留关联表全部数据

问题原因

你当前的查询把c_Docks.name = 'dock 1'放在了全局WHERE条件中,会过滤掉所有关联dock不符合该条件的行,相当于直接把LEFT JOIN的其他dock记录全部排除,所以只能拿到名称为dock 1的结果。


方案1:使用EXISTS子查询(推荐,性能更优)

通过子查询判断当前marine是否存在至少一个名称为dock 1的dock,不会影响外层关联返回的所有dock记录。

修改后SQL

SELECT `c`.`id`                AS `c_id`,
       `c`.`name`              AS `c_name`,
       `c`.`description`       AS `c_description`,
       `c`.`FkId`              AS `c_FkId`,
       `c`.`FkModel`           AS `c_FkModel`,
       `c`.`isActive`          AS `c_isActive`,
       `c`.`createdAt`         AS `c_createdAt`,
       `c`.`updatedAt`         AS `c_updatedAt`,
       `c`.`phones`            AS `c_phones`,
       `c`.`emails`            AS `c_emails`,
       `c`.`mainImage`         AS `c_mainImage`,
       `c`.`galleryImages`     AS `c_galleryImages`,
       `c`.`addressDetailsId`  AS `c_addressDetailsId`,
       `c_Docks`.`id`          AS `c_Docks_id`,
       `c_Docks`.`name`        AS `c_Docks_name`,
       `c_Docks`.`description` AS `c_Docks_description`,
       `c_Docks`.`FkId`        AS `c_Docks_FkId`,
       `c_Docks`.`FkModel`     AS `c_Docks_FkModel`,
       `c_Docks`.`isActive`    AS `c_Docks_isActive`,
       `c_Docks`.`createdAt`   AS `c_Docks_createdAt`,
       `c_Docks`.`updatedAt`   AS `c_Docks_updatedAt`,
       `c_Docks`.`MarineId`    AS `c_Docks_MarineId`
FROM `marine` `c`
LEFT JOIN `dock` `c_Docks` ON `c_Docks`.`MarineId` = `c`.`id`
WHERE `c`.`isActive` = true
  AND EXISTS (
    SELECT 1 FROM `dock` 
    WHERE `dock`.`MarineId` = `c`.`id` 
      AND `dock`.`name` = 'dock 1'
  )
# ORDER BY c_id DESC

对应TypeORM QueryBuilder写法(typeorm@0.2.37适用)

import { getConnection } from 'typeorm';
import { Marine } from './entity/Marine'; // 替换为你自己的Marine实体路径
import { Dock } from './entity/Dock'; // 替换为你自己的Dock实体路径

const result = await getConnection()
  .createQueryBuilder(Marine, 'c')
  // 假设Marine实体中关联Dock的属性名为docks,根据你的实际实体配置修改
  .leftJoinAndSelect('c.docks', 'c_Docks')
  .where('c.isActive = :isActive', { isActive: true })
  .andWhere((qb) => {
    const subQuery = qb
      .subQuery()
      .select('1')
      .from(Dock, 'dock')
      .where('dock.MarineId = c.id')
      .andWhere('dock.name = :dockName', { dockName: 'dock 1' })
      .getQuery();
    return `EXISTS ${subQuery}`;
  })
  // .orderBy('c.id', 'DESC')
  .getMany();

方案2:先查符合条件的Marine ID再关联查询

逻辑更直观,适合数据量不大的场景。

对应TypeORM QueryBuilder写法

import { getConnection } from 'typeorm';
import { Marine } from './entity/Marine';
import { Dock } from './entity/Dock';

// 第一步:查询所有存在dock 1的marine id
const validMarineIds = await getConnection()
  .createQueryBuilder(Dock, 'dock')
  .select('DISTINCT dock.MarineId', 'id')
  .where('dock.name = :dockName', { dockName: 'dock 1' })
  .getRawMany<{ id: number }>()
  .then(res => res.map(item => item.id));

// 第二步:查询这些marine的所有关联dock
const result = await getConnection()
  .createQueryBuilder(Marine, 'c')
  .leftJoinAndSelect('c.docks', 'c_Docks')
  .where('c.isActive = :isActive', { isActive: true })
  .andWhere('c.id IN (:...ids)', { ids: validMarineIds })
  // .orderBy('c.id', 'DESC')
  .getMany();

内容的提问来源于stack exchange,提问作者Lazt Omen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 03:54:06