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:

https://docs.sqlalchemy.org/en/20/orm/extensions/hybrid.html#correlated-subquery-relationship-hybrid

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

On Sun, Oct 29, 2023 at 9:51 AM Nik <gitbra...@gmail.com> wrote:

> 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()
>
> --
> 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+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sqlalchemy/d6ccf7c1-fd12-4fb8-b16d-5280f54d506an%40googlegroups.com
> <https://groups.google.com/d/msgid/sqlalchemy/d6ccf7c1-fd12-4fb8-b16d-5280f54d506an%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/CAFHwexdKp5z%3D9CE5WdJMw7ntmSwGxRxCigO0EiqVuwr-YO9R8A%40mail.gmail.com.

Reply via email to