Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL and SQLAlchemy: getting N recent comments for multiple items

I am trying to write a query to get the N most recent comments for multiple items.

Currently, I am looping through the items with a query per item:

for i in itemIds:
    Comment.query.filter_by(itemId=i).order_by(Comment.id.desc()).limit(3)

But this is really slow.

I would like to have a single query that gets all of the comments, but don't know how. I have tried using union but haven't gotten it to work. I appears there are issues with MySQL, order_by, and union. I am trying something to the effect of:

a = Comment.query.filter_by(itemId=1).order_by(Comment.id.desc()).limit(3)
b = Comment.query.filter_by(itemId=2).order_by(Comment.id.desc()).limit(3)
u = union_all(a,b)
DB.session.query(Comment).select_from(u).all()

But that doesn't work. It complains about 'Incorrect usage of UNION and ORDER BY'.

I'm not a MySQL or SQLAlchemy ninja, and have been banging my head on this for hours.

Help please! Any pointers or advice would be greatly appreciated.

like image 202
aspiringwebninja Avatar asked Feb 26 '13 11:02

aspiringwebninja


People also ask

What does First () do in SQLAlchemy?

first() applies a limit of one within the generated SQL, so that only one primary entity row is generated on the server side (note this may consist of multiple result rows if join-loaded collections are present). Calling Query. first() results in an execution of the underlying query.

Does SQLAlchemy work with MySQL?

SQLAlchemy provides a nice “Pythonic” way of interacting with databases. So rather than dealing with the differences between specific dialects of traditional SQL such as MySQL or PostgreSQL or Oracle, you can leverage the Pythonic framework of SQLAlchemy to streamline your workflow and more efficiently query your data.

What is lazy dynamic SQLAlchemy?

lazy = 'dynamic': When querying with lazy = 'dynamic', however, a separate query gets generated for the related object. If you use the same query as 'select', it will return: You can see that it returns a sqlalchemy object instead of the city objects.

Should I use SQLAlchemy core or ORM?

If you have data for which business objects are not needed, use Core. If you view your data as business objects, use ORM. If you are building a quick prototype, use ORM. If you have a combination of needs that really could leverage both business objects and other data unrelated to the problem domain, use both!


1 Answers

For the SQL version, please see the "Select the top N rows from each group" section in http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

which gives in SQLAlchemy:

c2 = aliased(Comment)
query = session.query(Comment).filter(
            session.query(func.count(c2.id))\
                .filter(c2.id >= Comment.id)\
                .filter(c2.item_id == Comment.item_id)\
                .order_by(c2.id.desc())\
                .correlate(Comment)\
                .as_scalar() <= 3)\
    .filter(Comment.item_id.in_(itemIds)).all()
like image 141
benselme Avatar answered Sep 22 '22 00:09

benselme