Skip to content

Add topk aggregation metadata and list endpoint - #400

Open
zipdoki wants to merge 16 commits into
mainfrom
feature/per-entity-top-k-meta
Open

Add topk aggregation metadata and list endpoint#400
zipdoki wants to merge 16 commits into
mainfrom
feature/per-entity-top-k-meta

Conversation

@zipdoki

@zipdoki zipdoki commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduce top-K aggregation metadata on Group and expose a read endpoint listing tables that declare one.

A Group can now carry an Aggregations block. Today only topk is defined; the schema is designed so future aggregation kinds (e.g. HLL) can land as sibling fields without restructuring the payload.

GET /graph/v3/aggregations returns a flat list of (type, database, table) tuples for every table that declares an aggregation, filterable by ?type=. The aggregate/mutate flow that consumes this metadata is out of scope for this PR and will land separately.

Metadata example

A group inside a label creation payload:

{
  "groups": [
    {
      "group": "purchased_count",
      "type": "COUNT",
      "fields": [{"name": "_target"}],
      "directionType": "OUT",
      "aggregations": {
        "topk": [
          {
            "topk": "top_purchased",
            "entity": "_source",
            "ranges": "_target:eq:{_target}",
            "dimension": "_target",
            "refreshAfterMillis": 31536000000,
            "rank": "commerce.purchases__topk"
          }
        ]
      }
    }
  ]
}

Endpoint example

GET /graph/v3/aggregations

{
  "items": [
    { "type": "TOPK", "database": "commerce", "table": "purchases" }
  ]
}

GET /graph/v3/aggregations?type=TOPK filters to a single aggregation type.

Test plan

  • ./gradlew :core:test --tests 'com.kakao.actionbase.core.metadata.common.AggregationsTest'
  • ./gradlew :engine:test --tests 'com.kakao.actionbase.engine.service.AggregationServiceSpec'
  • ./gradlew :engine:test --tests 'com.kakao.actionbase.v2.engine.entity.LabelEntityFunctionsSpec'
  • ./gradlew :server:test --tests 'com.kakao.actionbase.server.api.graph.v3.metadata.MetadataAggControllerE2ETest'

AI Assistance

  • This PR was written largely with AI assistance.
    • Tool / model: Claude Code (Opus 4.7)

@zipdoki zipdoki self-assigned this Jul 8, 2026
@zipdoki
zipdoki requested a review from em3s as a code owner July 8, 2026 08:00
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request labels Jul 8, 2026
@zipdoki
zipdoki removed the request for review from em3s July 8, 2026 08:09
@em3s

em3s commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

As we discussed offline about the expire / refresh terminology:

expire implies the value is invalid at that point., but it's still valid, just due for a refresh.

Could you rename these throughout the PR?

  • expireAfterMillisrefreshAfterMillis
  • the expire boolean → refresh (it means "needs to be refreshed")

Also, since we decided the refresh table will be a single system-wide table, TopkTable no longer needs the expire field.

@zipdoki

Base automatically changed from feat/multi-edge-agg-property-map to main July 15, 2026 05:54
zipdoki and others added 4 commits July 16, 2026 15:45
# Conflicts:
#	engine/src/main/kotlin/com/kakao/actionbase/v2/engine/Graph.kt
#	engine/src/main/kotlin/com/kakao/actionbase/v2/engine/v3/V2BackedTableBinding.kt
… `supportedTypes`, and enhance `AggregationsListResponse` structure.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
}, ;

abstract fun has(aggregations: Aggregations): Boolean
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Might look like overkill for a single variant, but a second aggregation kind is planned in a follow-up. Keeping the extension surface to "one enum case + one matching field on Aggregations" — every consumer (isEmpty, supports, LabelEntity.hasAggregation, toQualifiedAggregations) routes through here and stays untouched when new kinds land.

@zipdoki

zipdoki commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

@em3s
Thanks! Applied in 123210c:

  • expireAfterMillisrefreshAfterMillis
  • Dropped TopkTable.expire

The boolean expire was already removed earlier on this branch when the user/system aggregation paths were unified, so no rename needed there.

Ready for another look.

zipdoki added a commit that referenced this pull request Jul 16, 2026
Follow-up on the terminology change from #400: the score row is still
valid at the refresh timestamp, just due for a rebuild. Applied end-to-
end so the aggregate flow and its persisted schema line up:

- `AggregationConstants`: `TOPK_EXPIRE_TABLE` / `_PARTITIONS` and
  `expireSource` / `expireTarget` renamed
- `AggregationService`: local `expiresAt` and property key
  `"expiresAt"` renamed
- Refresh tracker table schema: column `expiresAt` → `refreshAt`,
  index `expires_at_asc` → `refresh_at_asc`, table comment updated

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jul 22, 2026
@zipdoki
zipdoki force-pushed the feature/per-entity-top-k-meta branch from bcdb6f6 to bd16d71 Compare July 22, 2026 09:46
@dosubot dosubot Bot removed the size:XL This PR changes 500-999 lines, ignoring generated files. label Jul 22, 2026
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants