I have 2 models: Post
and PostLike
. I want to return a query of Posts filtered by their PostLike created_at
field, as well as return the total count of posts in that query efficiently (without using .count()
).
Simplified models:
class Post(db.Model):
...
post_likes = db.relationship('PostLike', back_populates="post")
class PostLike(db.Model):
...
created_at = db.column(db.Float)
post_id = db.Column(UUID(as_uuid=True), db.ForeignKey("post.id"), index=True)
post = db.relationship("Post", back_populates="post_likes", foreign_keys=[post_id])
Here are the queries I'm trying to run:
# Get all posts
posts = Post.query.join(PostLike, Post.post_likes).order_by(PostLike.created_at.desc()).all()
# Get total # of posts
posts = Post.query.join(PostLike, Post.post_likes).order_by(PostLike.created_at.desc()).count()
There are 3 problems with those queries.
I'm not sure those queries are the best for my use case. Are they?
The query returns the wrong number as count. The count query returns a number higher than the results of the
.all()
query. Why?This is not performant as it is calling directly
.count()
. How do I implement an efficient query to also retrieve the count? Something like.statement.with_only_columns([func.count()])
?
I'm using Postgres, and I'm expecting up to millions of rows to count. How do I achieve this efficiently?