Skip to content

feat(dashboards): add collection tagging system#1289

Open
fhennig wants to merge 5 commits into
mainfrom
feature/collection-tagging
Open

feat(dashboards): add collection tagging system#1289
fhennig wants to merge 5 commits into
mainfrom
feature/collection-tagging

Conversation

@fhennig

@fhennig fhennig commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

resolves #1265

Summary

Implements tags on collections: database schema, CRUD support, tag
filtering on GET /collections, and a new GET /collections/tags endpoint
for frontend autocomplete.

Screenshot

n/a

PR Checklist

  • All necessary documentation has been adapted.
  • The implemented feature is covered by an appropriate test.

Felix Hennig and others added 2 commits June 24, 2026 15:03
Implements tags on collections: database schema, CRUD support, tag
filtering on GET /collections, and a new GET /collections/tags endpoint
for frontend autocomplete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the separate batch query for tags with a PostgreSQL string_agg
aggregate over a three-table JOIN (collections × variants × tags),
eliminating the extra round-trip to the database. Uses GROUP BY to
avoid the cartesian product:
- includeVariants=true: GROUP BY (c.id, v.id) + string_agg(tag ORDER BY tag)
- includeVariants=false: GROUP BY c.id + COUNT(DISTINCT v.id) + string_agg(DISTINCT tag)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dashboards Ready Ready Preview, Comment Jun 25, 2026 11:59am

Request Review

@fhennig fhennig self-assigned this Jun 25, 2026
@fhennig fhennig changed the title Add collection tagging system (issue #1265) feat(dashboards): add collection tagging system Jun 25, 2026
fhennig and others added 2 commits June 25, 2026 13:37
…subquery

Instead of iterating over tags and intersecting ID sets in Kotlin
(one query per tag), use a single subquery:

  SELECT collection_id FROM collection_tags
  WHERE tag IN (...)
  GROUP BY collection_id
  HAVING COUNT(DISTINCT tag) = N

This keeps the filter as one round-trip and avoids materializing ID
sets in application memory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d of in-memory sort

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class tag support to backend “collections” so the frontend can store, retrieve, and filter collections by free-text labels, plus fetch a global tag list for autocomplete.

Changes:

  • Introduces collection_tags junction table + Exposed table mapping, and persists tags on collection create/update.
  • Extends collection DTOs to include tags, adds tag-filtering to GET /collections (AND semantics), and adds GET /collections/tags.
  • Adds controller/integration tests covering tag CRUD behavior, filtering, normalization, and tag-list endpoint.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
backend/src/test/kotlin/org/genspectrum/dashboardsbackend/controller/CollectionsTagsTest.kt New integration tests for tag persistence, filtering semantics, and tags endpoint.
backend/src/test/kotlin/org/genspectrum/dashboardsbackend/controller/CollectionsClient.kt Extends test client to support tags query params and /collections/tags.
backend/src/main/resources/db/migration/V1.5__add_collection_tags.sql Adds collection_tags table with lowercase constraint + index.
backend/src/main/kotlin/org/genspectrum/dashboardsbackend/model/collection/CollectionTagsTable.kt New Exposed table + string_agg helper used for tag aggregation.
backend/src/main/kotlin/org/genspectrum/dashboardsbackend/model/collection/CollectionTable.kt Includes tags when mapping entities to API Collection.
backend/src/main/kotlin/org/genspectrum/dashboardsbackend/model/collection/CollectionModel.kt Implements tag CRUD, tag filtering, aggregation into responses, and “all tags” query.
backend/src/main/kotlin/org/genspectrum/dashboardsbackend/controller/CollectionsController.kt Adds tags query param to GET /collections and new GET /collections/tags endpoint.
backend/src/main/kotlin/org/genspectrum/dashboardsbackend/api/Collection.kt Adds tags to DTOs and defines CollectionTagsResponse.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 84 to 88
description = first[CollectionTable.description],
variantCount = variants.size,
variants = variants,
tags = first[tagsExpr]?.split(",") ?: emptyList(),
createdAt = first[CollectionTable.createdAt],
Comment on lines 116 to 119
variantCount = row[countExpr].toInt(),
variants = null,
tags = row[tagsExpr]?.split(",")?.sorted() ?: emptyList(),
createdAt = row[CollectionTable.createdAt],
variantEntity
}

val insertedTags = request.tags.map { it.lowercase() }.distinct().sorted()

if (update.tags != null) {
CollectionTagsTable.deleteWhere { CollectionTagsTable.collectionId eq id }
val newTags = update.tags.map { it.lowercase() }.distinct()
}
}
if (!tags.isNullOrEmpty()) {
val distinctTags = tags.map { it.lowercase() }.distinct()
Comment on lines 38 to 42
val params = buildString {
val queryParams = mutableListOf<String>()
if (userId != null) queryParams.add("userId=$userId")
if (organism != null) queryParams.add("organism=$organism")
if (includeVariants) queryParams.add("includeVariants=true")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(backend): collection tagging

2 participants