valor diferente de sqlalchemy de `len (query.all ())` y `query.count ()`

Este es un código de ejemplo.

Un documento tiene muchos comentarios

PostComment amplía el comentario (con la característica polimórfica sqlalchemy)

Algunas consultas devuelven resultados diferentes entre len(query.all()) y query.count()

  • Versión sqlalchemy: 1.0.8
  • Versión mysql: 5.6.25

Ver la función principal a continuación.

¿Que pasó?

 from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, scoped_session from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Table, Column, Integer, Float, Boolean, ForeignKey, String, Unicode, DateTime, Date, UniqueConstraint from sqlalchemy.orm import relationship, backref engine = create_engine('mysql://root:root@192.168.59.103:3306/document') DBSession = scoped_session(sessionmaker(bind=engine)) Base = declarative_base() Base.metadata.bind = engine class Document(Base): __tablename__ = 'document' id = Column(Integer, primary_key=True) class Comment(Base): __tablename__ = 'comment' id = Column(Integer, primary_key=True) type = Column(String(50)) document_id = Column(Integer, ForeignKey('document.id'), primary_key=True) document = relationship('Document', backref=backref('comments', lazy='dynamic')) __mapper_args__= { 'polymorphic_identity' : 'comment', 'polymorphic_on' : type, } class PostComment(Comment): __tablename__ = 'post_comment' id = Column(Integer, ForeignKey('comment.id'), primary_key=True) ready = Column(Boolean) __mapper_args__= { 'polymorphic_identity' : 'post_comment', } def main(): Base.metadata.drop_all(engine) Base.metadata.create_all(engine) d1 = Document() DBSession.add(d1) d2 = Document() DBSession.add(d2) c1 = PostComment(document=d1, ready=True) DBSession.add(c1) c2 = PostComment(document=d1, ready=True) DBSession.add(c2) c3 = PostComment(document=d2, ready=True) DBSession.add(c3) c4 = PostComment(document=d2, ready=True) DBSession.add(c4) DBSession.commit() query = d1.comments.filter(PostComment.ready==True) print len(query.all()) # returns 2 print query.count() # returns 8 if __name__ == '__main__': main() 

Actualizaciones

http://docs.sqlalchemy.org/en/rel_1_0/orm/query.html#sqlalchemy.orm.query.Query.count

Dice “Devolver un recuento de filas que devolvería esta consulta”.

Related of "valor diferente de sqlalchemy de `len (query.all ())` y `query.count ()`"

¿Por qué obtienes 8 como resultado en lugar de 2? Porque obtienes una consulta que es un producto cartesiano (8 = 2 * 2 * 2).
A su vez, esto sucede porque tiene dynamic relación dynamic con la inheritance , que crea una select de ambas tablas ( comment y post_comment ) sin ningún predicado entre ellas.

¿Por qué la primera consulta devuelve solo 2 ? Bueno, debido a que está solicitando instancias reales asignadas, sqlalchemy es lo suficientemente inteligente como para filtrar los duplicados, aunque la instrucción SQL subyacente también devuelve 8 filas.

Agrega una join a tu consulta para arreglar esto:

 query = d1.comments.join(PostComment).filter(PostComment.ready == True)