SQLAlchemy union \u all and all()返回的项数不正确

2024-06-16 14:35:29 发布

您现在位置:Python中文网/ 问答频道 /正文

出于某种原因,当我使用SQLAlchemy的union_all.all()时,它返回的项数不正确。你知道吗

正如你在下面看到的,我把每一个都分解了,看看错误在哪里。有人知道为什么会这样吗?你知道吗

>>> pn = PostNotification.query.filter_by(notified_id=1)
>>> cn = CommentNotification.query.filter_by(notified_id=1)
>>> pn.count()
4
>>> cn.count()
2
>>> u = pn.union_all(cn)
>>> u.count()
6
>>> all = u.all()
>>> len(all)
5

以下是我的两个模型:

class NotificationMixin:
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), nullable=False)
    read = db.Column(db.Boolean, default=False)
    created = db.Column(db.DateTime, index=True, default=datetime.utcnow)

    @declared_attr
    def notifier_id(cls):
        return db.Column(db.Integer, db.ForeignKey('user.id'))

    @declared_attr
    def notified_id(cls):
        return db.Column(db.Integer, db.ForeignKey('user.id'))


class PostNotification(db.Model, NotificationMixin):
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
    comment_id = db.Column(db.Integer)

    def __repr__(self):
        return '<PostNotification {}>'.format(self.name)


class CommentNotification(db.Model, NotificationMixin):
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
    comment_id = db.Column(db.Integer, db.ForeignKey('post_comment.id'))

    def __repr__(self):
        return '<CommentNotification {}>'.format(self.name)

更新

Here is a screenshot of the data that represents the two models

当我显式定义列时,当我使用union_all时没有问题。它只在I db.session.query(PostNotification)db.session.query(CommentNotification)时返回不正确的记录量。你知道吗

pn = db.session.query(
    PostNotification.id,
    PostNotification.name,
    PostNotification.read,
    PostNotification.created,
    PostNotification.post_id,
    PostNotification.comment_id,
    PostNotification.notifier_id,
    PostNotification.notified_id).filter_by(
        notified_id=1)

cn = db.session.query(
    CommentNotification.id,
    CommentNotification.name,
    CommentNotification.read,
    CommentNotification.created,
    CommentNotification.post_id,
    CommentNotification.comment_id,
    CommentNotification.notifier_id,
    CommentNotification.notified_id).filter_by(
        notified_id=1)

u = pn.union_all(cn).order_by(PostNotification.created.desc())

>>> pn.count()
4
>>> cn.count()
2
u.count()
6
>>> all = u.all()
>>> len(all)
6

问题是,我失去了模型,我的关系也消失了。因此,我不得不使用这个非常丑陋的解决方法。只有在https://i.stack.imgur.com/UHfo7.jpg中看到数据时,这才有意义。你知道吗

result = []
for row in u:
    if 'post' in row.name.split('_'):
        n = PostNotification.query.filter_by(id=row.id).first()
        result.append(n)
    if 'comment' in row.name.split('_'):
        n = CommentNotification.query.filter_by(id=row.id).first()
        result.append(n)

现在我的result按降序排列,两个表通过union_all合并,我的关系又回到了tact中。现在的问题是,我显然不能使用结果.分页,因为result现在是list。你知道吗


Tags: nameiddbbycolumnintegerallcn
2条回答

看来我知道了。我现在可以直接查询AbstractNotificationdb.session.query(AbstractNotification).all()

from sqlalchemy.ext.declarative import AbstractConcreteBase   


class AbstractNotification(AbstractConcreteBase, db.Model):
    __table__ = None


class NotificationBaseModel:
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), nullable=False)
    read = db.Column(db.Boolean, default=False)
    created = db.Column(db.DateTime, index=True, default=datetime.utcnow)

    @declared_attr
    def notifier_id(cls):
        return db.Column(db.Integer, db.ForeignKey('user.id'))

    @declared_attr
    def notified_id(cls):
        return db.Column(db.Integer, db.ForeignKey('user.id'))


class PostNotification(AbstractNotification, NotificationBaseModel):
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
    comment_id = db.Column(db.Integer)

    __mapper_args__ = {
        'polymorphic_identity': 'post_notification',
        'concrete': True
        }

    def __repr__(self):
        return '<PostNotification {}>'.format(self.name)


class CommentNotification(AbstractNotification, NotificationBaseModel):
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
    comment_id = db.Column(db.Integer, db.ForeignKey('post_comment.id'))

    __mapper_args__ = {
        'polymorphic_identity': 'comment_notification',
        'concrete': True
        }

    def __repr__(self):
        return '<CommentNotification {}>'.format(self.name)

联合u不是多态的,因为它可以识别哪些行代表PostNotification和哪些CommentNotification实体—它只是将所有行都视为代表主实体PostNotification。你知道吗

两个表中都有两个“相同”的通知,即它们的主键值相同。SQLAlchemy重复数据消除在查询时基于主键对模型实体进行删除,as noted here by the author of SQLAlchemy,因此len(u.all())返回的结果较少。u.count()另一方面,对数据库中的进行计数,从而对所有行进行计数。如果查询属性或多个实体,则不会执行此重复数据消除。你知道吗

相关问题 更多 >