我尝试通过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
}
]
正如我所说,在此处使用跳过/接听将给我错误的结果。如何达到预期的输出?
答案 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