diff --git a/src/Support/Reports/Volumes/ImageAnnotations/AnnotationReportGenerator.php b/src/Support/Reports/Volumes/ImageAnnotations/AnnotationReportGenerator.php index ea16136..3df60f8 100644 --- a/src/Support/Reports/Volumes/ImageAnnotations/AnnotationReportGenerator.php +++ b/src/Support/Reports/Volumes/ImageAnnotations/AnnotationReportGenerator.php @@ -113,7 +113,7 @@ public function initQuery($columns = []) ->when($this->isRestrictedToExportArea(), [$this, 'restrictToExportAreaQuery']) ->when($this->isRestrictedToAnnotationSession(), [$this, 'restrictToAnnotationSessionQuery']) ->when($this->isRestrictedToNewestLabel(), function ($query) { - return $this->restrictToNewestLabelQuery($query, 'image_annotation_labels'); + return $this->restrictToNewestLabelQuery($query, $this->source); }) ->when($this->isRestrictedToLabels(), function ($query) { return $this->restrictToLabelsQuery($query, 'image_annotation_labels'); diff --git a/src/Support/Reports/Volumes/ImageIfdoReportGenerator.php b/src/Support/Reports/Volumes/ImageIfdoReportGenerator.php index 5af8942..ca64feb 100644 --- a/src/Support/Reports/Volumes/ImageIfdoReportGenerator.php +++ b/src/Support/Reports/Volumes/ImageIfdoReportGenerator.php @@ -47,7 +47,7 @@ protected function query() }, 'annotations.labels' => function ($query) { if ($this->isRestrictedToNewestLabel()) { - $query = $this->restrictToNewestLabelQuery($query, 'image_annotation_labels'); + $query = $this->restrictToNewestLabelQuery($query, $this->source); } if ($this->isRestrictedToLabels()) { diff --git a/src/Support/Reports/Volumes/VideoAnnotations/CsvReportGenerator.php b/src/Support/Reports/Volumes/VideoAnnotations/CsvReportGenerator.php index 39daee2..f9b15f3 100644 --- a/src/Support/Reports/Volumes/VideoAnnotations/CsvReportGenerator.php +++ b/src/Support/Reports/Volumes/VideoAnnotations/CsvReportGenerator.php @@ -152,7 +152,7 @@ public function initQuery($columns = []) ->where('videos.volume_id', $this->source->id) ->when($this->isRestrictedToAnnotationSession(), [$this, 'restrictToAnnotationSessionQuery']) ->when($this->isRestrictedToNewestLabel(), function ($query) { - return $this->restrictToNewestLabelQuery($query, 'video_annotation_labels'); + return $this->restrictToNewestLabelQuery($query, $this->source); }) ->when($this->isRestrictedToLabels(), function ($query) { return $this->restrictToLabelsQuery($query, 'video_annotation_labels'); diff --git a/src/Support/Reports/Volumes/VideoIfdoReportGenerator.php b/src/Support/Reports/Volumes/VideoIfdoReportGenerator.php index 210c2b6..d8ba028 100644 --- a/src/Support/Reports/Volumes/VideoIfdoReportGenerator.php +++ b/src/Support/Reports/Volumes/VideoIfdoReportGenerator.php @@ -42,7 +42,7 @@ protected function query() }, 'annotations.labels' => function ($query) { if ($this->isRestrictedToNewestLabel()) { - $query = $this->restrictToNewestLabelQuery($query, 'video_annotation_labels'); + $query = $this->restrictToNewestLabelQuery($query, $this->source); } if ($this->isRestrictedToLabels()) { diff --git a/src/Traits/RestrictsToNewestLabels.php b/src/Traits/RestrictsToNewestLabels.php index 7f28c9d..9e09baa 100644 --- a/src/Traits/RestrictsToNewestLabels.php +++ b/src/Traits/RestrictsToNewestLabels.php @@ -2,7 +2,7 @@ namespace Biigle\Modules\Reports\Traits; -use Biigle\Modules\Reports\Volume; +use Biigle\Volume; use DB; trait RestrictsToNewestLabels @@ -11,27 +11,39 @@ trait RestrictsToNewestLabels * Callback to be used in a `when` query statement that restricts the results to the * newest annotation labels of each annotation. * - * @param \Illuminate\Database\Query\Builder $query - * @param string $table Name of the annotation label DB table * @return \Illuminate\Database\Query\Builder */ - public function restrictToNewestLabelQuery($query, $table) + public function restrictToNewestLabelQuery($query, Volume $volume) { // The subquery join is the fastest approach I could come up with that can be used // as an addition to the existing query (instead of rewiriting the entire query, // e.g. with a window function). // // Previously this was a where/in statement with was much slower. - // - // It could still be sped up with joins on image_annotations and images in the - // subquery, filtering it by volume_id, but this will be incompatible with video - // annotations. Maybe add a $mediaType argument to switch between tables? - $subquery = DB::table($table) - ->selectRaw("distinct on (annotation_id) id") - ->orderBy('annotation_id', 'desc') - ->orderBy('id', 'desc') - ->orderBy('created_at', 'desc'); + if ($volume->isVideoVolume()) { + $table = 'video_annotation_labels'; + + $subquery = DB::table($table) + ->selectRaw("distinct on (annotation_id) video_annotation_labels.id") + ->join('video_annotations', 'video_annotations.id', '=', 'video_annotation_labels.annotation_id') + ->join('videos', 'videos.id', '=', 'video_annotations.video_id') + ->where('volume_id', $volume->id) + ->orderBy('video_annotation_labels.annotation_id', 'desc') + ->orderBy('video_annotation_labels.id', 'desc') + ->orderBy('video_annotation_labels.created_at', 'desc'); + } else { + $table = 'image_annotation_labels'; + + $subquery = DB::table($table) + ->selectRaw("distinct on (annotation_id) image_annotation_labels.id") + ->join('image_annotations', 'image_annotations.id', '=', 'image_annotation_labels.annotation_id') + ->join('images', 'images.id', '=', 'image_annotations.image_id') + ->where('volume_id', $volume->id) + ->orderBy('image_annotation_labels.annotation_id', 'desc') + ->orderBy('image_annotation_labels.id', 'desc') + ->orderBy('image_annotation_labels.created_at', 'desc'); + } return $query->joinSub($subquery, 'latest_labels', fn ($join) => $join->on("{$table}.id", '=', 'latest_labels.id')); }