查找二阶关系:SQLAlchemy 抛出:"Please use the .select_from() method to establish an explicit left side"
Finding 2nd Order Relations: SQLAlchemy throws: "Please use the .select_from() method to establish an explicit left side"
我有一个 User
模型、一个 Contact
模型和一个 Group
模型。我希望在单个查询 中找到给定特定用户 的所有二阶 User
的 Group
。也就是说,我想:
- 使用特定用户的所有联系人...
- ...获取也是给定用户的联系人的所有用户,并将其用于...
- ...获取那些(二阶)用户的所有组
现在我有这样的东西(其中 user.id
是
我想查找其联系人的特定用户):
from sqlalchemy.orm import aliased
SecondOrderUser = aliased(User)
# This returns the phone number of all contacts who're a contact of the particular user
subquery = User.query \
.join(Contact, Contact.user_id == User.id) \
.filter(User.id == user.id) \
.with_entities(Contact.contact_phone) \
.subquery()
# This filters all users by the phone numbers in the above query, gets their contacts, and gets the group
# IDs of those contacts who are themselves users
contacts = User.query \
.filter(User.phone.in_(subquery)) \
.join(UserContact, UserContact.user_id == User.id) \
.join(SecondOrderUser, SecondOrderUser.phone == UserContact.phone) \
.join(Group, Group.user_id == SecondOrderUser.id) \
.with_entities(Group.id) \
.all()
Contact
和 User
唯一共享的东西(link 他们在一起——也就是说,找到自己是用户的联系人)是一个共同的 phone数字。我 [认为我] 也可以用四个 join
语句和别名来做到这一点,但这给了我同样的错误。即:
sqlalchemy.exc.InvalidRequestError: Can't determine which FROM clause to join from,
there are multiple FROMS which can join to this entity. Please use the .select_from()
method to establish an explicit left side, as well as providing an explicit ON clause
if not present already to help resolve the ambiguity.
我在这里做错了什么? Where/how加入对我来说很清楚,这表明我完全错过了一些东西。
这里的问题有两个。我们必须在每次使用 时为 table 添加别名(不仅仅是第二次以后),并且在使用 with_entities
时,我们必须使用我们比较的所有列——即使我们最终不打算使用它们的数据。
我的最终代码如下所示:
from sqlalchemy.orm import aliased
User1 = aliased(User)
User2 = aliased(User)
User3 = aliased(User)
Contact1 = aliased(Contact)
Contact2 = aliased(Contact)
contacts = User1.query \
.join(Contact1, Contact1.user_id == User1.id) \
.join(User2, User2.phone == Contact1.phone) \
.join(Contact2, Contact2.user_id == User2.id) \
.join(User3, User3.phone == Contact2.phone) \
.join(Group, Group.user_id == User3.id) \
.with_entities(
Contact1.phone,
Contact1.user_id,
Contact2.phone,
Contact2.user_id,
Group.id
Group.user_id,
User1.id,
User2.id,
User2.phone,
User3.id,
User3.phone,
) \
.all()
我有一个 User
模型、一个 Contact
模型和一个 Group
模型。我希望在单个查询 中找到给定特定用户 的所有二阶 User
的 Group
。也就是说,我想:
- 使用特定用户的所有联系人...
- ...获取也是给定用户的联系人的所有用户,并将其用于...
- ...获取那些(二阶)用户的所有组
现在我有这样的东西(其中 user.id
是
我想查找其联系人的特定用户):
from sqlalchemy.orm import aliased
SecondOrderUser = aliased(User)
# This returns the phone number of all contacts who're a contact of the particular user
subquery = User.query \
.join(Contact, Contact.user_id == User.id) \
.filter(User.id == user.id) \
.with_entities(Contact.contact_phone) \
.subquery()
# This filters all users by the phone numbers in the above query, gets their contacts, and gets the group
# IDs of those contacts who are themselves users
contacts = User.query \
.filter(User.phone.in_(subquery)) \
.join(UserContact, UserContact.user_id == User.id) \
.join(SecondOrderUser, SecondOrderUser.phone == UserContact.phone) \
.join(Group, Group.user_id == SecondOrderUser.id) \
.with_entities(Group.id) \
.all()
Contact
和 User
唯一共享的东西(link 他们在一起——也就是说,找到自己是用户的联系人)是一个共同的 phone数字。我 [认为我] 也可以用四个 join
语句和别名来做到这一点,但这给了我同样的错误。即:
sqlalchemy.exc.InvalidRequestError: Can't determine which FROM clause to join from,
there are multiple FROMS which can join to this entity. Please use the .select_from()
method to establish an explicit left side, as well as providing an explicit ON clause
if not present already to help resolve the ambiguity.
我在这里做错了什么? Where/how加入对我来说很清楚,这表明我完全错过了一些东西。
这里的问题有两个。我们必须在每次使用 时为 table 添加别名(不仅仅是第二次以后),并且在使用 with_entities
时,我们必须使用我们比较的所有列——即使我们最终不打算使用它们的数据。
我的最终代码如下所示:
from sqlalchemy.orm import aliased
User1 = aliased(User)
User2 = aliased(User)
User3 = aliased(User)
Contact1 = aliased(Contact)
Contact2 = aliased(Contact)
contacts = User1.query \
.join(Contact1, Contact1.user_id == User1.id) \
.join(User2, User2.phone == Contact1.phone) \
.join(Contact2, Contact2.user_id == User2.id) \
.join(User3, User3.phone == Contact2.phone) \
.join(Group, Group.user_id == User3.id) \
.with_entities(
Contact1.phone,
Contact1.user_id,
Contact2.phone,
Contact2.user_id,
Group.id
Group.user_id,
User1.id,
User2.id,
User2.phone,
User3.id,
User3.phone,
) \
.all()