mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-10 21:01:10 +03:00
Remove the CTE and restore the generator with sub-queries, which is more performance (thanks Nick and Blake for testing against your larger DB!)
This commit is contained in:
+73
-77
@@ -392,6 +392,15 @@ def events_explore(
|
|||||||
if not allowed_cameras:
|
if not allowed_cameras:
|
||||||
return JSONResponse(content=[])
|
return JSONResponse(content=[])
|
||||||
|
|
||||||
|
distinct_labels = (
|
||||||
|
Event.select(Event.label)
|
||||||
|
.where(Event.camera << allowed_cameras)
|
||||||
|
.distinct()
|
||||||
|
.order_by(Event.label)
|
||||||
|
)
|
||||||
|
|
||||||
|
label_counts = {}
|
||||||
|
|
||||||
explore_columns = (
|
explore_columns = (
|
||||||
Event.id,
|
Event.id,
|
||||||
Event.camera,
|
Event.camera,
|
||||||
@@ -410,86 +419,73 @@ def events_explore(
|
|||||||
Event.data,
|
Event.data,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Single query: per-label COUNT and top-N ranking by start_time computed
|
def event_generator():
|
||||||
# via window functions in a CTE, then filtered to rn <= limit
|
for label_obj in distinct_labels.iterator():
|
||||||
event_count = (
|
label = label_obj.label
|
||||||
fn.COUNT(Event.id).over(partition_by=[Event.label]).alias("event_count")
|
|
||||||
)
|
|
||||||
rn = (
|
|
||||||
fn.ROW_NUMBER()
|
|
||||||
.over(partition_by=[Event.label], order_by=[Event.start_time.desc()])
|
|
||||||
.alias("rn")
|
|
||||||
)
|
|
||||||
|
|
||||||
base_query = Event.select(
|
# get most recent events for this label
|
||||||
*explore_columns,
|
label_events = (
|
||||||
event_count,
|
Event.select(*explore_columns)
|
||||||
rn,
|
.where((Event.label == label) & (Event.camera << allowed_cameras))
|
||||||
).where(Event.camera << allowed_cameras)
|
.order_by(Event.start_time.desc())
|
||||||
ranked = base_query.cte("ranked")
|
.limit(limit)
|
||||||
query = (
|
.iterator()
|
||||||
Event.select(
|
)
|
||||||
ranked.c.id,
|
|
||||||
ranked.c.camera,
|
# count total events for this label
|
||||||
ranked.c.label,
|
label_counts[label] = (
|
||||||
ranked.c.sub_label,
|
Event.select()
|
||||||
ranked.c.zones,
|
.where((Event.label == label) & (Event.camera << allowed_cameras))
|
||||||
ranked.c.start_time,
|
.count()
|
||||||
ranked.c.end_time,
|
)
|
||||||
ranked.c.has_clip,
|
|
||||||
ranked.c.has_snapshot,
|
yield from label_events
|
||||||
ranked.c.plus_id,
|
|
||||||
ranked.c.retain_indefinitely,
|
def process_events():
|
||||||
ranked.c.top_score,
|
for event in event_generator():
|
||||||
ranked.c.false_positive,
|
processed_event = {
|
||||||
ranked.c.box,
|
"id": event.id,
|
||||||
ranked.c.data,
|
"camera": event.camera,
|
||||||
ranked.c.event_count,
|
"label": event.label,
|
||||||
)
|
"zones": event.zones,
|
||||||
.from_(ranked)
|
"start_time": event.start_time,
|
||||||
.with_cte(ranked)
|
"end_time": event.end_time,
|
||||||
.where(ranked.c.rn <= limit)
|
"has_clip": event.has_clip,
|
||||||
.order_by(ranked.c.event_count.desc(), ranked.c.start_time.desc())
|
"has_snapshot": event.has_snapshot,
|
||||||
.objects()
|
"plus_id": event.plus_id,
|
||||||
|
"retain_indefinitely": event.retain_indefinitely,
|
||||||
|
"sub_label": event.sub_label,
|
||||||
|
"top_score": event.top_score,
|
||||||
|
"false_positive": event.false_positive,
|
||||||
|
"box": event.box,
|
||||||
|
"data": {
|
||||||
|
k: v
|
||||||
|
for k, v in event.data.items()
|
||||||
|
if k
|
||||||
|
in [
|
||||||
|
"type",
|
||||||
|
"score",
|
||||||
|
"top_score",
|
||||||
|
"description",
|
||||||
|
"sub_label_score",
|
||||||
|
"average_estimated_speed",
|
||||||
|
"velocity_angle",
|
||||||
|
"path_data",
|
||||||
|
"recognized_license_plate",
|
||||||
|
"recognized_license_plate_score",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"event_count": label_counts[event.label],
|
||||||
|
}
|
||||||
|
yield processed_event
|
||||||
|
|
||||||
|
# convert iterator to list and sort
|
||||||
|
processed_events = sorted(
|
||||||
|
process_events(),
|
||||||
|
key=lambda x: (x["event_count"], x["start_time"]),
|
||||||
|
reverse=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
allowed_data_keys = {
|
|
||||||
"type",
|
|
||||||
"score",
|
|
||||||
"top_score",
|
|
||||||
"description",
|
|
||||||
"sub_label_score",
|
|
||||||
"average_estimated_speed",
|
|
||||||
"velocity_angle",
|
|
||||||
"path_data",
|
|
||||||
"recognized_license_plate",
|
|
||||||
"recognized_license_plate_score",
|
|
||||||
}
|
|
||||||
|
|
||||||
processed_events = [
|
|
||||||
{
|
|
||||||
"id": event.id,
|
|
||||||
"camera": event.camera,
|
|
||||||
"label": event.label,
|
|
||||||
"zones": event.zones,
|
|
||||||
"start_time": event.start_time,
|
|
||||||
"end_time": event.end_time,
|
|
||||||
"has_clip": event.has_clip,
|
|
||||||
"has_snapshot": event.has_snapshot,
|
|
||||||
"plus_id": event.plus_id,
|
|
||||||
"retain_indefinitely": event.retain_indefinitely,
|
|
||||||
"sub_label": event.sub_label,
|
|
||||||
"top_score": event.top_score,
|
|
||||||
"false_positive": event.false_positive,
|
|
||||||
"box": event.box,
|
|
||||||
"data": {
|
|
||||||
k: v for k, v in (event.data or {}).items() if k in allowed_data_keys
|
|
||||||
},
|
|
||||||
"event_count": event.event_count,
|
|
||||||
}
|
|
||||||
for event in query
|
|
||||||
]
|
|
||||||
|
|
||||||
return JSONResponse(content=processed_events)
|
return JSONResponse(content=processed_events)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user