查找二阶关系: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 模型。我希望在单个查询 中找到给定特定用户 的所有二阶 UserGroup。也就是说,我想:

  • 使用特定用户的所有联系人...
  • ...获取也是给定用户的联系人的所有用户,并将其用于...
  • ...获取那些(二阶)用户的所有组

现在我有这样的东西(其中 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()

ContactUser 唯一共享的东西(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()