Eager load get_posts for submission_listings.
Ported in logic from upstream to use SQLAlchemy eager loading instead of repeated queries when building a submission_listing. Adjusted loaded relationships to include only those used on TheMotte. Using test data from seed_db, before and after: GET / |----------|--------|--------|--------|--------|--------|------------| | Database | SELECT | INSERT | UPDATE | DELETE | Totals | Duplicates | |----------|--------|--------|--------|--------|--------|------------| | default | 83 | 0 | 0 | 0 | 83 | 72 | |----------|--------|--------|--------|--------|--------|------------| Total queries: 83 in 0.031s GET / |----------|--------|--------|--------|--------|--------|------------| | Database | SELECT | INSERT | UPDATE | DELETE | Totals | Duplicates | |----------|--------|--------|--------|--------|--------|------------| | default | 14 | 0 | 0 | 0 | 14 | 0 | |----------|--------|--------|--------|--------|--------|------------| Total queries: 14 in 0.00718s
This commit is contained in:
parent
9953c5763c
commit
4d22d9bce2
5 changed files with 24 additions and 10 deletions
|
@ -33,7 +33,9 @@ class Badge(Base):
|
||||||
Index('badges_badge_id_idx', badge_id)
|
Index('badges_badge_id_idx', badge_id)
|
||||||
|
|
||||||
user = relationship("User", viewonly=True)
|
user = relationship("User", viewonly=True)
|
||||||
badge = relationship("BadgeDef", primaryjoin="foreign(Badge.badge_id) == remote(BadgeDef.id)", viewonly=True)
|
badge = relationship("BadgeDef",
|
||||||
|
primaryjoin="foreign(Badge.badge_id) == remote(BadgeDef.id)",
|
||||||
|
lazy="joined", innerjoin=True, viewonly=True)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Badge(user_id={self.user_id}, badge_id={self.badge_id})>"
|
return f"<Badge(user_id={self.user_id}, badge_id={self.badge_id})>"
|
||||||
|
|
|
@ -2,6 +2,7 @@ from typing import Iterable, List, Optional, Type, Union
|
||||||
|
|
||||||
from flask import g
|
from flask import g
|
||||||
from sqlalchemy import and_, any_, or_
|
from sqlalchemy import and_, any_, or_
|
||||||
|
from sqlalchemy.orm import selectinload
|
||||||
|
|
||||||
from files.classes import *
|
from files.classes import *
|
||||||
from files.helpers.const import AUTOJANNY_ID
|
from files.helpers.const import AUTOJANNY_ID
|
||||||
|
@ -148,7 +149,8 @@ def get_post(
|
||||||
|
|
||||||
def get_posts(
|
def get_posts(
|
||||||
pids:Iterable[int],
|
pids:Iterable[int],
|
||||||
v:Optional[User]=None) -> List[Submission]:
|
v:Optional[User]=None,
|
||||||
|
eager:bool=False) -> List[Submission]:
|
||||||
if not pids: return []
|
if not pids: return []
|
||||||
|
|
||||||
if v:
|
if v:
|
||||||
|
@ -177,6 +179,16 @@ def get_posts(
|
||||||
else:
|
else:
|
||||||
query = g.db.query(Submission).filter(Submission.id.in_(pids))
|
query = g.db.query(Submission).filter(Submission.id.in_(pids))
|
||||||
|
|
||||||
|
if eager:
|
||||||
|
query = query.options(
|
||||||
|
selectinload(Submission.author).options(
|
||||||
|
selectinload(User.badges),
|
||||||
|
selectinload(User.notes),
|
||||||
|
),
|
||||||
|
selectinload(Submission.reports),
|
||||||
|
selectinload(Submission.awards),
|
||||||
|
)
|
||||||
|
|
||||||
results = query.all()
|
results = query.all()
|
||||||
|
|
||||||
if v:
|
if v:
|
||||||
|
|
|
@ -204,7 +204,7 @@ def front_all(v, sub=None, subdomain=None):
|
||||||
site=SITE
|
site=SITE
|
||||||
)
|
)
|
||||||
|
|
||||||
posts = get_posts(ids, v=v)
|
posts = get_posts(ids, v=v, eager=True)
|
||||||
|
|
||||||
if v:
|
if v:
|
||||||
if v.hidevotedon: posts = [x for x in posts if not hasattr(x, 'voted') or not x.voted]
|
if v.hidevotedon: posts = [x for x in posts if not hasattr(x, 'voted') or not x.voted]
|
||||||
|
|
|
@ -160,7 +160,7 @@ def searchposts(v):
|
||||||
next_exists = (len(ids) > 25)
|
next_exists = (len(ids) > 25)
|
||||||
ids = ids[:25]
|
ids = ids[:25]
|
||||||
|
|
||||||
posts = get_posts(ids, v=v)
|
posts = get_posts(ids, v=v, eager=True)
|
||||||
|
|
||||||
if request.headers.get("Authorization"): return {"total":total, "data":[x.json for x in posts]}
|
if request.headers.get("Authorization"): return {"total":total, "data":[x.json for x in posts]}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ def upvoters_posts(v, username, uid):
|
||||||
next_exists = len(listing) > 25
|
next_exists = len(listing) > 25
|
||||||
listing = listing[:25]
|
listing = listing[:25]
|
||||||
|
|
||||||
listing = get_posts(listing, v=v)
|
listing = get_posts(listing, v=v, eager=True)
|
||||||
|
|
||||||
return render_template("voted_posts.html", next_exists=next_exists, listing=listing, page=page, v=v)
|
return render_template("voted_posts.html", next_exists=next_exists, listing=listing, page=page, v=v)
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ def downvoters_posts(v, username, uid):
|
||||||
next_exists = len(listing) > 25
|
next_exists = len(listing) > 25
|
||||||
listing = listing[:25]
|
listing = listing[:25]
|
||||||
|
|
||||||
listing = get_posts(listing, v=v)
|
listing = get_posts(listing, v=v, eager=True)
|
||||||
|
|
||||||
return render_template("voted_posts.html", next_exists=next_exists, listing=listing, page=page, v=v)
|
return render_template("voted_posts.html", next_exists=next_exists, listing=listing, page=page, v=v)
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ def upvoting_posts(v, username, uid):
|
||||||
next_exists = len(listing) > 25
|
next_exists = len(listing) > 25
|
||||||
listing = listing[:25]
|
listing = listing[:25]
|
||||||
|
|
||||||
listing = get_posts(listing, v=v)
|
listing = get_posts(listing, v=v, eager=True)
|
||||||
|
|
||||||
return render_template("voted_posts.html", next_exists=next_exists, listing=listing, page=page, v=v)
|
return render_template("voted_posts.html", next_exists=next_exists, listing=listing, page=page, v=v)
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ def downvoting_posts(v, username, uid):
|
||||||
next_exists = len(listing) > 25
|
next_exists = len(listing) > 25
|
||||||
listing = listing[:25]
|
listing = listing[:25]
|
||||||
|
|
||||||
listing = get_posts(listing, v=v)
|
listing = get_posts(listing, v=v, eager=True)
|
||||||
|
|
||||||
return render_template("voted_posts.html", next_exists=next_exists, listing=listing, page=page, v=v)
|
return render_template("voted_posts.html", next_exists=next_exists, listing=listing, page=page, v=v)
|
||||||
|
|
||||||
|
@ -824,7 +824,7 @@ def u_username(username, v=None):
|
||||||
for p in sticky:
|
for p in sticky:
|
||||||
ids = [p.id] + ids
|
ids = [p.id] + ids
|
||||||
|
|
||||||
listing = get_posts(ids, v=v)
|
listing = get_posts(ids, v=v, eager=True)
|
||||||
|
|
||||||
if u.unban_utc:
|
if u.unban_utc:
|
||||||
if request.headers.get("Authorization"): {"data": [x.json for x in listing]}
|
if request.headers.get("Authorization"): {"data": [x.json for x in listing]}
|
||||||
|
@ -1105,7 +1105,7 @@ def saved_posts(v, username):
|
||||||
|
|
||||||
ids=ids[:25]
|
ids=ids[:25]
|
||||||
|
|
||||||
listing = get_posts(ids, v=v)
|
listing = get_posts(ids, v=v, eager=True)
|
||||||
|
|
||||||
if request.headers.get("Authorization"): return {"data": [x.json for x in listing]}
|
if request.headers.get("Authorization"): return {"data": [x.json for x in listing]}
|
||||||
return render_template("userpage.html",
|
return render_template("userpage.html",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue