How correct sort items by @hibrid_property

16 views
Skip to first unread message

Nik

unread,
Oct 29, 2023, 5:51:16 AM10/29/23
to sqlalchemy
Hello, guys!
I have a simple code, which not correct work
He throw error if i try sort items by @hybrid_property

My version of entity class:
class Product(Base) :

    __tablename__ = 'products'

    Id = Column('id', Integer, primary_key=True, autoincrement=True)
    TitleTranslit = Column('title_translit', String)
    Title = Column('title', String)
    Description = Column('description', String)
    CurrentPrice = Column('current_price', Integer)
    OldPrice = Column('old_price', Integer)
    CategoryId = Column('category_id', Integer, ForeignKey('categories.id'))
    Characteristics:List[ProductCharacteristic] = relationship('ProductCharacteristic', primaryjoin="and_(ProductCharacteristic.ProductId==Product.Id)", lazy='joined')
    Reviews:List[ProductReview] = relationship('ProductReview', primaryjoin="and_(ProductReview.ProductId==Product.Id)", lazy='joined')
    Images:List[ProductImage] = relationship('ProductImage', primaryjoin="and_(ProductImage.ProductId==Product.Id)", lazy='joined')
    NumberOfViews = Column('number_of_views', Integer)

    @hybrid_property
    def Rating(self) :
        result = 0
        reviewsCount = len(self.Reviews)
        if (reviewsCount > 0) :
            for review in self.Reviews :
                result += review.Rating
            result = result / reviewsCount
        return result


My version of call sort event by @hybrid_property:
filteredProductsQuery = self._sessionService.DBContext.query(Product)\
            .filter(Product.CategoryId.in_(categoriesIds)).outerjoin(Product.Characteristics)

        if sortType == SortType.HighestRate.value :
            filteredProductsQuery = filteredProductsQuery.order_by(Product.Rating.desc())

Throwed error if i try execute this query:
TypeError: object of type 'InstrumentedAttribute' has no len()

Simon King

unread,
Oct 30, 2023, 7:36:52 AM10/30/23
to sqlal...@googlegroups.com
The error you're getting doesn't have anything to do with using the property in an order_by. It's being triggered just by accessing "Product.Rating". WIth hybrid properties, when you access them via the class as you've done here, the "self" parameter is set to the Product class itself. So on the second line of the function, you are actually saying "reviewsCount = len(Product.Reviews)", which doesn't make any sense.

You need to define a separate implementation of the hybrid property that returns an SQL construct so that it can be embedded in an SQL query, using the "<propertyname>.expression" decorator. Since you need to access a separate table to calculate your Rating, you probably need a correlated subquery, something like this:


That example uses "func.sum" to calculate a sum over the related rows. For your purposes, you probably want "func.avg" to calculate the mean.

(Note that the performance of this query is going to get worse as the number of products and ratings increases)

Hope that helps,

Simon

--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
 
http://www.sqlalchemy.org/
 
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/d6ccf7c1-fd12-4fb8-b16d-5280f54d506an%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages