Saya memiliki kelas yang dipetakan SQLAlchemy berikut:
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"))
Saya perlu mendapatkan meja seperti ini untuk user.email = "[email protected]"
:
email | name | document_name | document_readAllowed | document_writeAllowed
Bagaimana cara membuatnya menggunakan satu permintaan kueri untuk SQLAlchemy? Kode di bawah tidak berfungsi untuk saya:
result = session.query(User, Document, DocumentPermission).filter_by(email = "[email protected]").all()
Terima kasih,
python
sql
join
sqlalchemy
barankin
sumber
sumber
result = session.query(User, Document).select_from(join(User, Document)).filter(User.email=='[email protected]').all()
Tapi saya belum berhasil bagaimana membuat pekerjaan serupa untuk tiga tabel (untuk menyertakan DocumentPermissions). Ada ide?Jawaban:
Coba ini
q = Session.query( User, Document, DocumentPermissions, ).filter( User.email == Document.author, ).filter( Document.name == DocumentPermissions.document, ).filter( User.email == 'someemail', ).all()
sumber
join
apa yang dilakukannya? batin, luar, salib atau apa?[(<user>, <document>, <documentpermissions>),...]
/select x from a, b ,c
yang merupakan gabungan silang. Filter kemudian membuatnya menjadi gabungan dalam..all()
. Jadiprint Session.query....
untuk melihat dengan tepat apa yang dilakukannya..filter()
dapat menerima beberapa kriteria jika dipisahkan dengan koma. Apakah lebih baik menggunakan satu.filter()
dengan pemisah koma di dalam tanda kurung, atau menggunakan banyak.filter()
seperti jawaban di atas?Gaya yang baik adalah mengatur beberapa relasi dan kunci utama untuk izin (sebenarnya, biasanya itu adalah gaya yang baik untuk menyiapkan kunci primer integer untuk semuanya, tetapi apa pun):
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')
Kemudian lakukan kueri sederhana dengan gabungan:
query = session.query(User, Document, DocumentsPermissions).join(Document).join(DocumentsPermissions)
sumber
query
diatur di baris terakhir dan bagaimana Anda mengakses rekaman yang digabungkan di dalamnya?Document
(nilai tuple ke-2) di set hasil kueri?for (user, doc, perm) in query: print "Document: %s" % doc
Seperti yang dikatakan @letitbee, praktik terbaiknya adalah menetapkan kunci utama ke tabel dan menentukan hubungan dengan benar untuk memungkinkan kueri ORM yang tepat. Yang telah dibilang...
Jika Anda tertarik untuk menulis kueri di sepanjang baris:
SELECT user.email, user.name, document.name, documents_permissions.readAllowed, documents_permissions.writeAllowed FROM user, document, documents_permissions WHERE user.email = "[email protected]";
Maka Anda harus mencari sesuatu seperti:
session.query( User, Document, DocumentsPermissions ).filter( User.email == Document.author ).filter( Document.name == DocumentsPermissions.document ).filter( User.email == "[email protected]" ).all()
Jika sebaliknya, Anda ingin melakukan sesuatu seperti:
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
Maka Anda harus melakukan sesuatu di sepanjang baris:
session.query( User ).join( Document ).join( DocumentsPermissions ).filter( User.email == "[email protected]" ).all()
Satu catatan tentang itu ...
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
Untuk informasi lebih lanjut, kunjungi dokumen .
sumber
Memperluas jawaban Abdul, Anda bisa mendapatkan
KeyedTuple
kumpulan baris terpisah dengan menggabungkan kolom:q = Session.query(*User.__table__.columns + Document.__table__.columns).\ select_from(User).\ join(Document, User.email == Document.author).\ filter(User.email == 'someemail').all()
sumber
Fungsi ini akan menghasilkan tabel yang dibutuhkan sebagai daftar tupel.
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)
sumber