我的数据库中有这些表(PostgreSQL):
events(id, title, starts_at, ends_at, ...)
reservations(id, event_id, ...)
reservation_messages(id, reservation_id, ...)
我有API调用:/api/v1/host/events
必须返回json事件数组,但数组中的每个json对象必须包含两个额外的字段reservations_count
和unread_messages_count
。此外,我只需要尚未结束的事件,这意味着ends_at
列大于now()
我正在考虑加载这些“计数”字段的最有效方法。 下一个查询给出了我想要的结果,但我不知道它的效率如何:
$user->host->events()
->where('ends_at', '>', Carbon::now())
->withCount([
'reservations',
'reservationMessages AS unread_messages' => function($query) {
$query->where('seen', false);
}
])
->get()
这将产生大的查询,并且会有很多连接:
select "events".*, (select count(*) from "reservations" where "events"."id" = "reservations"."event_id") as "reservations_count", (select count(*) from "reservation_messages" inner join "reservations" on "reservations"."id" = "reservation_messages"."reservation_id" where "events"."id" = "reservations"."event_id" and "seen" = ?) as "unread_messages_count" from "events" where "events"."host_id" = ? and ("events"."host_id") is not null and "ends_at" > ? and ("events"."deleted_at") is null
是否有更有效的方法来加载所需的结果,因为我认为这个查询在包含大量数据的数据库上会非常慢?
答案 0 :(得分:0)
您可以在关系之间使用with()将查询链接在一起,以便快速加载。如果您关注数据库大小和执行时间,只需在集合中检索记录后计算记录,并附加一个动态属性,其中包含预留计数和一个未读消息。在内存中处理集合很快,并且可以省去数据库查询。