From a29da46bfec812d46df3b5a967429ff7a238d2b5 Mon Sep 17 00:00:00 2001 From: Felix Stupp Date: Sat, 19 Nov 2022 23:21:29 +0100 Subject: [PATCH] generate_preference_list: Use SQL to retrieve tags of elements --- server/entertainment_decider/models.py | 43 ++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/server/entertainment_decider/models.py b/server/entertainment_decider/models.py index 5072981..bec9662 100644 --- a/server/entertainment_decider/models.py +++ b/server/entertainment_decider/models.py @@ -8,6 +8,7 @@ from datetime import datetime, timedelta from functools import cache import gzip from itertools import chain +import itertools import json import math import logging @@ -20,6 +21,7 @@ from typing import ( Mapping, NewType, Optional, + Sequence, Set, Tuple, TypeAlias, @@ -423,9 +425,10 @@ def generate_preference_list( # score calc now = datetime.now() - @cache + elem_tag_map = get_all_elements_tags_recursive() + def all_tags(element: MediaElement) -> List[Tag]: - return [tag for tag in element.all_tags if tag.use_for_preferences] + return elem_tag_map.get(element.id, []) # TODO prepare static score in parallel (or cache it in DB for longer) @cache @@ -1330,6 +1333,42 @@ def get_all_considered( ) +def get_all_elements_tags_recursive() -> Mapping[int, Sequence[Tag]]: + elem_tag_query: Iterable[Tuple[int, int]] = db.execute( + """ + WITH RECURSIVE found_tag (mediaelement_id, tag_id) AS + ( + SELECT mediaelement_tag.mediaelement, mediaelement_tag.tag + FROM mediaelement_tag + UNION + SELECT mediacollectionlink.element, mediacollection_tag.tag + FROM mediacollectionlink + JOIN mediacollection_tag ON mediacollectionlink.collection = mediacollection_tag.mediacollection + UNION + SELECT found_tag.mediaelement_id, tag_tag.tag_2 + FROM found_tag + JOIN tag_tag ON found_tag.tag_id = tag_tag.tag + ) + SELECT found_tag.mediaelement_id, found_tag.tag_id + FROM found_tag + JOIN tag ON found_tag.tag_id = tag.id + WHERE tag.use_for_preferences + ORDER BY mediaelement_id, tag_id; + """ + ) + + @cache + def get_tag(tag_id: int) -> Tag: + return Tag[tag_id] + + return { + elem_id: [get_tag(tag_id) for _, tag_id in group_iter] + for elem_id, group_iter in itertools.groupby( + elem_tag_query, key=lambda row: row[0] + ) + } + + def update_element_lookup_cache(collection_ids: List[int] = []): logging.info( f"Rebuild {MEDIAELEMENT_BLOCKING_LOOKUP_CACHE_TABLE} for {len(collection_ids) if collection_ids else 'all'} collections …"