Python Flask SQLAlchemy-根据匹配多对多对象的数量,按权重/分数排序结果
鉴于以下模型:Python Flask SQLAlchemy-根据匹配多对多对象的数量,按权重/分数排序结果,python,sqlalchemy,Python,Sqlalchemy,鉴于以下模型: class Tag(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Unicode(255)) taxonomy = db.Column(db.Unicode(), nullable=False) created_at = db.Column(db.DateTime, default=db.func.now()) updated_at
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(255))
taxonomy = db.Column(db.Unicode(), nullable=False)
created_at = db.Column(db.DateTime, default=db.func.now())
updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())
__mapper_args__ = {
'polymorphic_identity': 'tag',
'polymorphic_on': taxonomy,
'order_by': name
}
class FooTag(Tag):
id = db.Column(db.Integer, db.ForeignKey('tag.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity': 'foo'
}
class BarTag(Tag):
id = db.Column(db.Integer, db.ForeignKey('tag.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity': 'bar',
}
class Profile(db.Model):
foo_tags = db.relationship(
"FooTag",
secondary=profiles_tags,
secondaryjoin="and_(Tag.id==profiles_tags.c.tag_id, Tag.taxonomy=='foo')",
uselist=True,
lazy='dynamic'
)
bar_tags = db.relationship(
"BarTag",
secondary=profiles_tags,
secondaryjoin="and_(Tag.id==profiles_tags.c.tag_id, Tag.taxonomy=='bar')",
uselist=True,
lazy='dynamic'
)
我是否可以通过一组Tag
s筛选Profile
对象,然后根据匹配的Tag
s的数量对结果进行排序?即
foo_tags=[2, 4, 6]
bar_tags=[8, 22, 14]
results = Profile.join(Profile.foo_tags).filter(FooTag.id.in_(foo_tags)).\
join(Profile.bar_tags).filter(BarTag.id.in_(bar_tags)).\
paginate(1, 20)
其中,结果
的顺序取决于在每个返回的对象上找到多少匹配的foo_标签
/bar_标签
这是
Python==2.7
,Flask==0.12.2
,SQLAlchemy==1.1.11
,Flask SQLAlchemy==2.3.2
,因为您使用的是联合继承,所以FooTag
和BarTag
引用了标记的相同id域,无需根据foo\u标签
和bar\u标签
单独加入和筛选。相反,您可以加入Profile
和Tag
,或者甚至只加入Profile
和profiles\u tags
,通过键(如Profile.id
)进行过滤和分组,如果它有这样的主键(问题中的示例在这方面缺乏):
配置文件id作为一个分阶段符包含在订单中,因此您可以获得确定性分页。这是一个很好的解决方案,现在感觉非常明显。非常感谢。
results = Profile.query.\
join(profiles_tags).\
filter(profiles_tags.c.tag_id.in_(foo_tags + bar_tags)).\
group_by(Profile.id).\
order_by(func.count(), Profile.id)