From 0007a48c9cdcce63cd92d7c074982d1da858a5c7 Mon Sep 17 00:00:00 2001 From: smithellis Date: Tue, 21 Jan 2025 14:22:54 -0500 Subject: [PATCH] Decrease database hits and other requested changes --- kitsune/questions/views.py | 3 +-- kitsune/wiki/facets.py | 1 + kitsune/wiki/utils.py | 45 ++++++++++++++++++++++++++++++-------- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/kitsune/questions/views.py b/kitsune/questions/views.py index 86bbe7e6f4e..f729ed58fde 100644 --- a/kitsune/questions/views.py +++ b/kitsune/questions/views.py @@ -570,10 +570,9 @@ def aaq(request, product_slug=None, step=1, is_loginless=False): if step == 2: topics = topics_for(request.user, product, parent=None) - topics_data = build_topics_data(request, product, topics) context["featured"] = get_featured_articles(product, locale=request.LANGUAGE_CODE) - context["topics"] = topics_data + context["topics"] = build_topics_data(request, product, topics) elif step == 3: context["cancel_url"] = get_next_url(request) or ( diff --git a/kitsune/wiki/facets.py b/kitsune/wiki/facets.py index 697d1684856..25b49670063 100644 --- a/kitsune/wiki/facets.py +++ b/kitsune/wiki/facets.py @@ -177,6 +177,7 @@ def _documents_for(user, locale, topics=None, products=None): document_summary=d.current_revision.summary, display_order=d.original.display_order, helpful_votes=votes_dict.get(d.current_revision_id, 0), + topics=d.topics.all().values_list("id", flat=True), ) ) diff --git a/kitsune/wiki/utils.py b/kitsune/wiki/utils.py index ba6693cf711..e5e993ea852 100644 --- a/kitsune/wiki/utils.py +++ b/kitsune/wiki/utils.py @@ -205,31 +205,58 @@ def get_visible_revision_or_404(user, **kwargs): def build_topics_data(request, product, topics): """Build topics_data for use in topic cards""" topics_data = [] + + # Get all documents for all topics up front + # Sadly documents_for doesn't return the actual document objects, it returns a list of dicts + # with the following keys: + # id + # document_title + # url + # document_parent_id + # created + # product_titles + # document_summary + # display_order + # helpful_votes + # topics + all_docs, _ = documents_for( + request.user, request.LANGUAGE_CODE, topics=list(topics), products=[product] + ) + + # Convert all docs to Document objects + doc_ids = [doc["id"] for doc in all_docs] + docs_by_id = {doc.id: doc for doc in Document.objects.filter(id__in=doc_ids)} + + # Create a mapping of Document objects to their topics from all_docs + for doc_dict in all_docs: + if doc := docs_by_id.get(doc_dict["id"]): + doc.topics_list = doc_dict.get("topics", []) + for topic in topics: - # Get featured articles first (returns up to 4) + # Get featured articles first (returns up to 4 Document objects) featured_articles = get_featured_articles( product, locale=request.LANGUAGE_CODE, topic=topic ) - # Always get total count of available documents - docs, _ = documents_for( - request.user, request.LANGUAGE_CODE, topics=[topic], products=[product] - ) - total_articles = Document.objects.filter(id__in=[doc["id"] for doc in docs]).count() + # Get docs for this topic from docs_by_id + topic_docs = [ + doc for doc in docs_by_id.values() if topic.id in getattr(doc, "topics_list", []) + ] # Only query for additional docs if we need more to reach 3 if len(featured_articles) < 3: - docs = Document.objects.filter(id__in=[doc["id"] for doc in docs]) - remaining_docs = [doc for doc in docs if doc not in featured_articles] + # If we don't have enough featured articles, append more from topic_docs + remaining_docs = [doc for doc in topic_docs if doc not in featured_articles] featured_articles.extend(remaining_docs) topic_data = { "topic": topic, "topic_url": reverse("products.documents", args=[product.slug, topic.slug]), "title": topic.title, - "total_articles": total_articles, + "total_articles": len(topic_docs), "image_url": topic.image_url, "documents": featured_articles[:3], } topics_data.append(topic_data) + return topics_data