繁体   English   中英

sqlalchemy 子查询和连接没有正确排序关系

[英]sqlalchemy subquery and join not ordering relationship correctly

我有两个表模型和图像。 这些表具有一对多关系,一个模型有多个图像。 我的图像 sqlalchemy 模型有一个属性,它是在子查询中设置的 query_expression,我想用它来对模型结果和模型图像进行排序。

使用子查询对模型进行排序,但不对模型的图像进行排序。 插入图像按 id 排序。

子查询不像我预期的那样工作,因为它似乎没有使用子查询中的图像,它似乎从数据库中获取新图像,这对我来说确实有意义,但不是我想要它做的。 我希望它使用来自子查询的图像,以便它们设置权重,我认为这也可以解决排序问题。 如果这是不可能的,我也很高兴将与模型相关的图像正确排序匹配子查询

我试图以多种不同的方式解决这个问题,这段代码是我迄今为止最接近的

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
db = SQLAlchemy(app)


class Image(db.Model):
    __tablename__ = 'images'

    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.Text)
    model_id = db.Column(db.ForeignKey('models.id'))

    weight = db.query_expression()

    model = db.relationship('Model', primaryjoin='Image.model_id == Model.id', backref="images")

    def __repr__(self):
        return f"<Image {self.id} {self.model_id} {self.weight}>"  # <Image id model_id weight>


class Model(db.Model):
    __tablename__ = 'models'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)
    url = db.Column(db.Text)


db.create_all()

test_data = [(496, [2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465]),
             (719, [3669, 3670, 3671, 3672, 3673, 3674, 3675, 5122]),
             (720, [3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684]), (721, [3685, 3686, 3687, 3688, 3689]),
             (957, [4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928])]
for model_id, image_ids in test_data:
    model = Model(id=model_id)
    for image_id in image_ids:
        model.images.append(Image(id=image_id, model_id=model_id))
    db.session.add(model)
db.session.commit()


@app.route('/')
def hello_world():
    image_ids = [5122, 3669, 2457, 3670, 2460, 3677, 2459, 3685, 3676, 2458, 4921, 4923, 3687,
                 4922, 3686, 3671, 4924, 4927, 2461, 3679, 3672, 2465, 3678, 3688, 3682, 3680,
                 4928, 3689, 4925, 3684, 2464, 4926, 3683, 2462, 3675, 3673, 3681, 2463, 3674]
    model_ids = [719, 496, 720, 721, 957]
    image_weights = [0.023905573, 0.82817817, 0.9049727, 0.9182812, 0.9498839, 0.9507337, 0.9895415, 1.0062627,
                     1.006611, 1.0194101, 1.0212375, 1.0346948, 1.053909, 1.095496, 1.0977578, 1.0993682, 1.1059334,
                     1.1750572, 1.1773994, 1.1993531, 1.1995214, 1.2016991, 1.2049828, 1.2159566, 1.2252866, 1.2271863,
                     1.245359, 1.248407, 1.2530898, 1.2567475, 1.2585162, 1.2642251, 1.2729594, 1.2750005, 1.2892585,
                     1.2958231, 1.296642, 1.3050407, 1.310439]

    case_statement = db.case([(uid == Image.id, weight) for uid, weight in zip(image_ids, image_weights)], else_=None) \
        .label("weight")
    images = db.session.query(Image).options(db.with_expression(Image.weight, case_statement)).order_by(
        "weight").filter(db.column("weight").isnot(None))
    images_subquery = images.subquery("images")
    models = db.session.query(Model).join(images_subquery)
    for model in models:
        print(model, model.images)
    return 'Hello World!'


if __name__ == '__main__':
    app.run()

转到 / 路线时的输出是

<Model 719> [<Image 3669 719 None>, <Image 3670 719 None>, <Image 3671 719 None>, <Image 3672 719 None>, <Image 3673 719 None>, <Image 3674 719 None>, <Image 3675 719 None>, <Image 5122 719 None>]
<Model 496> [<Image 2457 496 None>, <Image 2458 496 None>, <Image 2459 496 None>, <Image 2460 496 None>, <Image 2461 496 None>, <Image 2462 496 None>, <Image 2463 496 None>, <Image 2464 496 None>, <Image 2465 496 None>]
<Model 720> [<Image 3676 720 None>, <Image 3677 720 None>, <Image 3678 720 None>, <Image 3679 720 None>, <Image 3680 720 None>, <Image 3681 720 None>, <Image 3682 720 None>, <Image 3683 720 None>, <Image 3684 720 None>]
<Model 721> [<Image 3685 721 None>, <Image 3686 721 None>, <Image 3687 721 None>, <Image 3688 721 None>, <Image 3689 721 None>]
<Model 957> [<Image 4921 957 None>, <Image 4922 957 None>, <Image 4923 957 None>, <Image 4924 957 None>, <Image 4925 957 None>, <Image 4926 957 None>, <Image 4927 957 None>, <Image 4928 957 None>]

如您所见,模型已排序,但图像按 id 排序,重量为 None 我希望它们按重量排序,并希望像这样正确设置

<Model 719> [<Image 5122 719 0.023905573>, <Image 3669 719 0.82817817>, <Image 3670 719 0.9182812>, <Image 3671 719 1.0993682>, <Image 3672 719 1.1995214>, <Image 3675 719 1.2892585>, <Image 3673 719 1.2958231>, <Image 3674 719 1.310439>]
<Model 496> [<Image 2457 496 0.9049727>, <Image 2460 496 0.9498839>,<Image 2459 496 0.9895415>, <Image 2458 496 1.0194101>, <Image 2461 496 1.1773994>, <Image 2465 496 1.2016991>, <Image 2464 496 1.2585162>, <Image 2462 496 1.2750005>, <Image 2463 496 1.3050407>]
<Model 720> [<Image 3677 720 0.9507337>, <Image 3676 720 1.006611>, <Image 3679 720 1.1993531>, <Image 3678 720 1.2049828>, <Image 3682 720 1.2252866>, <Image 3680 720 1.2271863>, <Image 3684 720 1.2567475>, <Image 3683 720 1.2729594>, <Image 3681 720 1.296642>]
<Model 721> [<Image 3685 721 1.0062627>, <Image 3687 721 1.053909>, <Image 3686 721 1.0977578>, <Image 3688 721 1.2159566>, <Image 3689 721 1.248407>]
<Model 957> [<Image 4921 957 1.0212375>, <Image 4923 957 1.0346948>, <Image 4922 957 1.095496>, <Image 4924 957 1.1059334>, <Image 4927 957 1.1750572>, <Image 4928 957 1.245359>, <Image 4925 957 1.2530898>, <Image 4926 957 1.2642251>]

任何帮助是极大的赞赏

经过大量搜索 sqlalchemy 文档后,我找到了contains_eager 它告诉 SQLAlchemy 应该从查询中的列加载给定的关系。

models = Model.query.join(Image).order_by(case_statement).options(db.contains_eager(Model.images)).filter(Model.id.in_(model_ids))

为了让我的项目工作,我决定删除with_expressionquery_expression ,而只是在order_by()使用 case 语句

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM