[英]sqlalchemy: how to join several tables by one query?
I have the following SQLAlchemy mapped classes:我有以下 SQLAlchemy 映射类:
class User(Base):
__tablename__ = 'users'
email = Column(String, primary_key=True)
name = Column(String)
class Document(Base):
__tablename__ = "documents"
name = Column(String, primary_key=True)
author = Column(String, ForeignKey("users.email"))
class DocumentsPermissions(Base):
__tablename__ = "documents_permissions"
readAllowed = Column(Boolean)
writeAllowed = Column(Boolean)
document = Column(String, ForeignKey("documents.name"))
I need to get a table like this for user.email = "user@email.com"
:我需要为
user.email = "user@email.com"
获取这样的表:
email | name | document_name | document_readAllowed | document_writeAllowed
How can it be made using one query request for SQLAlchemy?如何使用 SQLAlchemy 的一个查询请求来实现? The code below does not work for me:
下面的代码对我不起作用:
result = session.query(User, Document, DocumentPermission).filter_by(email = "user@email.com").all()
Thanks,谢谢,
Try this尝试这个
q = Session.query(
User, Document, DocumentPermissions,
).filter(
User.email == Document.author,
).filter(
Document.name == DocumentPermissions.document,
).filter(
User.email == 'someemail',
).all()
A good style would be to setup some relations and a primary key for permissions (actually, usually it is good style to setup integer primary keys for everything, but whatever):一个好的风格是为权限设置一些关系和主键(实际上,通常为所有内容设置整数主键是一种很好的风格,但无论如何):
class User(Base):
__tablename__ = 'users'
email = Column(String, primary_key=True)
name = Column(String)
class Document(Base):
__tablename__ = "documents"
name = Column(String, primary_key=True)
author_email = Column(String, ForeignKey("users.email"))
author = relation(User, backref='documents')
class DocumentsPermissions(Base):
__tablename__ = "documents_permissions"
id = Column(Integer, primary_key=True)
readAllowed = Column(Boolean)
writeAllowed = Column(Boolean)
document_name = Column(String, ForeignKey("documents.name"))
document = relation(Document, backref = 'permissions')
Then do a simple query with joins:然后用连接做一个简单的查询:
query = session.query(User, Document, DocumentsPermissions).join(Document).join(DocumentsPermissions)
As @letitbee said, its best practice to assign primary keys to tables and properly define the relationships to allow for proper ORM querying.正如@letitbee 所说,将主键分配给表并正确定义关系以允许正确的 ORM 查询的最佳实践。 That being said...
话虽如此...
If you're interested in writing a query along the lines of:如果您有兴趣按照以下方式编写查询:
SELECT
user.email,
user.name,
document.name,
documents_permissions.readAllowed,
documents_permissions.writeAllowed
FROM
user, document, documents_permissions
WHERE
user.email = "user@email.com";
Then you should go for something like:那么你应该去寻找类似的东西:
session.query(
User,
Document,
DocumentsPermissions
).filter(
User.email == Document.author
).filter(
Document.name == DocumentsPermissions.document
).filter(
User.email == "user@email.com"
).all()
If instead, you want to do something like:如果相反,您想要执行以下操作:
SELECT 'all the columns'
FROM user
JOIN document ON document.author_id = user.id AND document.author == User.email
JOIN document_permissions ON document_permissions.document_id = document.id AND document_permissions.document = document.name
Then you should do something along the lines of:那么你应该按照以下方式做一些事情:
session.query(
User
).join(
Document
).join(
DocumentsPermissions
).filter(
User.email == "user@email.com"
).all()
One note about that...关于这一点的一个说明...
query.join(Address, User.id==Address.user_id) # explicit condition
query.join(User.addresses) # specify relationship from left to right
query.join(Address, User.addresses) # same, with explicit target
query.join('addresses') # same, using a string
Expanding on Abdul's answer, you can obtain a KeyedTuple
instead of a discrete collection of rows by joining the columns:扩展 Abdul 的答案,您可以通过连接列来获得
KeyedTuple
而不是离散的行集合:
q = Session.query(*User.__table__.columns + Document.__table__.columns).\
select_from(User).\
join(Document, User.email == Document.author).\
filter(User.email == 'someemail').all()
This function will produce required table as list of tuples.此函数将生成所需的表作为元组列表。
def get_documents_by_user_email(email):
query = session.query(
User.email,
User.name,
Document.name,
DocumentsPermissions.readAllowed,
DocumentsPermissions.writeAllowed,
)
join_query = query.join(Document).join(DocumentsPermissions)
return join_query.filter(User.email == email).all()
user_docs = get_documents_by_user_email(email)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.