簡體   English   中英

SQLAlchemy union_all和all()返回錯誤的項目數

[英]SQLAlchemy union_all and all() returning incorrect number of items

由於某些原因,當我使用SQLAlchemy的union_allunion_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)

更新

這是代表兩個模型的數據的屏幕截圖

當我顯式定義列時,使用union_all不會有問題。 僅在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合並union_all ,並且我的關系恢復了union_all 現在的問題是,我顯然不能使用result.paginate,因為result現在是一個list

聯合u在識別出哪些行代表PostNotification和哪個CommentNotification實體的意義上不是多態的,它只是將所有行都視為代表主要實體PostNotification

也可能在兩個表中都有2個“相同”的通知,即它們的主鍵數值相同。 SQLAlchemy在查詢時會基於主鍵對模型實體進行重復數據刪除, 正如SQLAlchemy的作者在此處指出的那樣 ,因此len(u.all())返回的結果較少。 u.count()數據庫中計數,因此對所有行進行計數。 如果查詢屬性或多於1個實體,則不會發生重復數據刪除。

好像我想通了。 我現在可以直接查詢AbstractNotification db.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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM