From 4ded8988c3e2e87296694062a476aaa7cb73f4cb Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 30 Aug 2023 18:42:03 +0700 Subject: [PATCH] add channel aggregation --- tubearchivist/api/src/aggs.py | 49 +++++++++++++++++++++++++++++++++++ tubearchivist/api/urls.py | 5 ++++ tubearchivist/api/views.py | 21 ++++++++++++++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/tubearchivist/api/src/aggs.py b/tubearchivist/api/src/aggs.py index 08259146..a829469c 100644 --- a/tubearchivist/api/src/aggs.py +++ b/tubearchivist/api/src/aggs.py @@ -124,3 +124,52 @@ class DownloadHist(AggBase): buckets = aggregations[self.name]["buckets"] return {i.get("key_as_string"): i.get("doc_count") for i in buckets} + + +class BiggestChannel(AggBase): + """get channel aggregations""" + + name = "channel_stats" + path = "ta_video/_search" + data = { + "size": 0, + "aggs": { + name: { + "multi_terms": { + "terms": [ + {"field": "channel.channel_name.keyword"}, + {"field": "channel.channel_id"}, + ], + "order": {"doc_count": "desc"}, + }, + "aggs": { + "doc_count": {"value_count": {"field": "_index"}}, + "duration": {"sum": {"field": "player.duration"}}, + "media_size": {"sum": {"field": "media_size"}}, + }, + }, + }, + } + order_choices = ["doc_count", "duration", "media_size"] + + def process(self, order_by=False): + """process aggregation""" + + if order_by and order_by in self.order_choices: + self.data["aggs"][self.name]["multi_terms"]["order"] = order_by + + aggregations = self.get() + buckets = aggregations[self.name]["buckets"] + + response = [ + { + "id": i["key"][1], + "name": i["key"][0].title(), + "doc_count": i["doc_count"]["value"], + "duration": i["duration"]["value"], + "media_size": i["media_size"]["value"], + } + for i in buckets + ] + + return response diff --git a/tubearchivist/api/urls.py b/tubearchivist/api/urls.py index 1e12ad78..6ad41638 100644 --- a/tubearchivist/api/urls.py +++ b/tubearchivist/api/urls.py @@ -151,4 +151,9 @@ urlpatterns = [ views.StatDownloadHist.as_view(), name="api-stats-downloadhist", ), + path( + "stats/biggestchannels/", + views.StatBiggestChannel.as_view(), + name="api-stats-biggestchannels", + ), ] diff --git a/tubearchivist/api/views.py b/tubearchivist/api/views.py index 704e53a4..cf9521f4 100644 --- a/tubearchivist/api/views.py +++ b/tubearchivist/api/views.py @@ -1,6 +1,6 @@ """all API views""" -from api.src.aggs import DownloadHist, Primary, WatchProgress +from api.src.aggs import BiggestChannel, DownloadHist, Primary, WatchProgress from api.src.search_processor import SearchProcess from home.src.download.queue import PendingInteract from home.src.download.subscriptions import ( @@ -1012,3 +1012,22 @@ class StatDownloadHist(ApiBaseView): # pylint: disable=unused-argument return Response(DownloadHist().process()) + + +class StatBiggestChannel(ApiBaseView): + """resolves to /api/stats/biggestchannels/ + GET: return biggest channels + param: order + """ + + order_choices = ["doc_count", "duration", "media_size"] + + def get(self, request): + """handle get request""" + + order = request.GET.get("order") + if order and order not in self.order_choices: + message = {"message": f"invalid order parameter {order}"} + return Response(message, status=400) + + return Response(BiggestChannel().process())