[英]SQLAlchemy union_all and all() returning incorrect number of items
由于某些原因,当我使用SQLAlchemy的union_all
和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)
更新 :
当我显式定义列时,使用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.