SQLAlchemy 中 join 和 joinedload 的区别

3
我有以下几个类:

Class User(Base):
    #user properties

Class Item(Base):
    #item properties

Class User_Item(Base):
    __tablename__='users_items'
    id=Column(Integer, primary_key=True)
    user_id=Column(Integer, ForeignKey('users.id'))
    item_id=Column(Integer, ForeignKey('items.id'))
    info=Column(String(20))
    user=relationship(User,backref='items',primaryjoin=(User.id==user_id))
    item=relationship(Item, backref='users',primaryjoin=(Item.id==item_id))

现在,以下两个查询有什么区别:

result1= session.query(Item).options(joinedload(Item.users)).filter(Item.users.any(user=user1)

或者

result2=session.query(Item).join(Item.users).filter(Item.users.any(user=user1))

由于某些原因,第二个看起来很奇怪!假设用户1有两个项目,运行result1.count()返回预期的2,但result2.count()返回3!而len(result2.all())是2!有人能告诉我发生了什么?! :D


你的查询有什么目标? - schlamar
例如,在这里我想找到所有映射到用户1的项目(而不使用user1.items!!!),或者一个更现实的例子是找到所有拥有'info="something"'的项目。我认为这是我可以通过第一个查询实现的,但我的问题是第一个查询和第二个查询有什么区别?! - Amin
我在你其他问题的回答 也可能解决这个问题。 - schlamar
1个回答

0

使用joinedload的第一种方法显然不是你想要的,因为它只定义了在执行查询后如何加载item.users(参见关系加载技术)。

而使用join时,你应该使用contains而不是any

result3 = session.query(Item).join(Item.users).filter(Item.users.contains(user1))

我猜你使用了any的版本,导致每个连接结果产生了多行。你可以通过检查生成的SQL语句(在引擎配置中设置echo=True)来验证这一点。

编辑

你可能错误地定义了多对多关系,这可能是真正的问题所在。在你的版本中,User.itemsItem.users都指向了User_Item,而不是User或Item,我想你可能没有意识到这一点。

你应该看一下关联对象模式以及如何简化它


首先,感谢您的回答,但我还有两个问题: 1-在第一种方法中,我尝试加载Item.users然后在其上进行查询,因为在加载之前无法对用户属性进行查询。它运行得很好,有没有具体的原因,为什么它不是我想要的? 2-运行您建议的查询时,出现了一个StatementError! - Amin
你的第一种方法只是比直接访问user1.items更复杂(没有添加任何实际好处)。第二种情况中到底出了什么错误?我仍然认为你想要一个动态关系,这样你可以使用User.items进行查询(例如user1.items.filter(Item.attribute==x).all())。 - schlamar
我同意,动态关系实际上解决了我的两个问题 :) 谢谢 :D - Amin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接