TypeORM-与leftJoinAndSelect一起使用Take / limit不能按预期工作

时间:2019-01-24 02:47:14

标签: typeorm

我尝试通过QueryBuilder获取一个关系表,直到我尝试使用跳过/偏移和取/限制,它都可以正常工作。我希望得到这样的回报:

[
    {
        "id": 1, // order.id
        "locations": [ ... ] array of locations with same order.id
    },
    {
        "id": 2,
        "locations": [ ... ]
    },
    {
        "id": 3,
        "locations": [ ... ]
    }
]

order.entity.ts

@PrimaryGeneratedColumn({ name: 'id' })
public id!: number;

@OneToMany((type) => Location, (location) => location.order, {
    onDelete: 'NO ACTION',
    onUpdate: 'NO ACTION',
})
public locations: Location[];

locations.entity.ts

@PrimaryGeneratedColumn({ name: 'id' })
public id!: number;

@ManyToOne((type) => Order, (order) => order.locations, {
    nullable: false,
    onDelete: 'NO ACTION',
    onUpdate: 'NO ACTION',
})
  @JoinColumn({ name: 'order_id' })
  public order: Order = null;

[查询A]我通过以下代码获得所需的输出:(但不使用跳过/获取,输出位于该问题的顶部)

const orders = getRepository(Order)
    .createQueryBuilder('order')
    .where('order.customer_id = :customer', { customer: user.id })
    .leftJoinAndSelect('order.locations', 'location', 'location.order_id = order.order_id')
    .getMany(); // output count is 35, output count with limit/take of 10 would be 10

[查询B]如果我添加跳过/偏移和取/限制,则看起来像这样:

const orders = getRepository(Order)
    .createQueryBuilder('order')
    .where('order.customer_id = :customer', { customer: user.id })
    .leftJoinAndSelect('order.locations', 'location', 'location.order_id = order.order_id')
    .skip(0)
    .limit(10)
    .getMany(); // output count is 5

但是在这里,输出正确,但是长度/计数完全错误。 查询A 查找总有2个位置的35个订单。如果我从查询A 中删除leftJoinAndSelect并添加跳过和带走,那么它将找到35个订单。但是查询B (限制/取10)使我的输出计数为5。输出减半!如果极限/止损等于8,则输出为4的长度。显然,getMany确实具有一些魔力,所以我发现了getRawMany,它将输出翻倍。因为对于每个订单,都有2个位置。那也不是我所需要的。而且此输出的结构也是错误的(如下所示)。 getManyRaw可以,但是如果我将其与skip / take一起使用,则不会,因为输出显然是错误的,因为我需要每个订单的所有位置。分组依据在这里无济于事,因为那样我每个订单只有1个位置。

getRawMany的输出就像

[
    {
        "order_id": 1,
        "locations_id": 100
    },
    {
        "order_id": 1,
        "locations_id": 101
    },
    {
        "id": 2,
        "locations_id": 102
    },
    {
        "id": 2,
        "locations_id": 103
    },
    {
        "id": 3,
        "locations_id": 104
    },
    {
        "id": 3,
        "locations_id": 105
    }
]

正如我所说,在此处使用跳过/接听将给我错误的结果。如何达到预期的输出?

1 个答案:

答案 0 :(得分:0)

我希望我能回答您的问题,基本上您想实现的是跳过并接受父订单,而不管它有多少子位置。这是正确的吗?

如果我的理解是正确的,则可以使用以下方法:

const orders = getRepository(Order) // use await if it inside async function
        .createQueryBuilder('order')
        .addSelect('@row_number := ' +
                'CASE WHEN @parent_id <> location.order_id ' +
                  'THEN @row_number + 1 ' +
                  'ELSE @row_number END AS rn, ' +
              '@parent_id := location.order_id'
         )
        .where('order.customer_id = :customer', { customer: user.id })
        .leftJoinAndSelect('order.locations', 'location', 'location.order_id = order.order_id')
        .innerJoin('(SELECT @row_number := 0)', 'init_row', '1 = 1')
        .innerJoin('(SELECT @parent_id := 0)', 'init_id', '1 = 1')
        .orderBy('location.order_id')
        .having('rn <= 10')
        .getMany(); // now output should be 10 in case u want to skip use rn > 10 AND rn <= 20 condition