SQLAlchemy ORM - Caricamento desideroso

Il carico desideroso riduce il numero di query. SQLAlchemy offre funzioni di caricamento desiderose invocate tramite opzioni di query che forniscono istruzioni aggiuntive alla query. Queste opzioni determinano come caricare vari attributi tramite il metodo Query.options ().

Sottoquery Load

Vogliamo che Customer.invoices venga caricato con entusiasmo. L'opzione orm.subqueryload () fornisce una seconda istruzione SELECT che carica completamente le raccolte associate ai risultati appena caricati. Il nome "sottoquery" fa sì che l'istruzione SELECT venga costruita direttamente tramite la query riutilizzata e incorporata come una sottoquery in una SELECT rispetto alla tabella correlata.

from sqlalchemy.orm import subqueryload
c1 = session.query(Customer).options(subqueryload(Customer.invoices)).filter_by(name = 'Govind Pant').one()

Ciò si traduce nelle seguenti due espressioni SQL:

SELECT customers.id 
AS customers_id, customers.name 
AS customers_name, customers.address 
AS customers_address, customers.email 
AS customers_email
FROM customers
WHERE customers.name = ?
('Govind Pant',)

SELECT invoices.id 
AS invoices_id, invoices.custid 
AS invoices_custid, invoices.invno 
AS invoices_invno, invoices.amount 
AS invoices_amount, anon_1.customers_id 
AS anon_1_customers_id
FROM (
   SELECT customers.id 
   AS customers_id
   FROM customers
   WHERE customers.name = ?) 
   
AS anon_1 
JOIN invoices 
ON anon_1.customers_id = invoices.custid 
ORDER BY anon_1.customers_id, invoices.id 2018-06-25 18:24:47,479 
INFO sqlalchemy.engine.base.Engine ('Govind Pant',)

Per accedere ai dati da due tabelle, possiamo utilizzare il programma seguente:

print (c1.name, c1.address, c1.email)

for x in c1.invoices:
   print ("Invoice no : {}, Amount : {}".format(x.invno, x.amount))

L'output del programma sopra è il seguente:

Govind Pant Gulmandi Aurangabad [email protected]
Invoice no : 3, Amount : 10000
Invoice no : 4, Amount : 5000

Carico unito

L'altra funzione si chiama orm.joinedload (). Questo emette un LEFT OUTER JOIN. L'oggetto principale e l'oggetto o la raccolta correlati vengono caricati in un unico passaggio.

from sqlalchemy.orm import joinedload
c1 = session.query(Customer).options(joinedload(Customer.invoices)).filter_by(name='Govind Pant').one()

Questo emette la seguente espressione dando lo stesso output di sopra -

SELECT customers.id 
AS customers_id, customers.name 
AS customers_name, customers.address 
AS customers_address, customers.email 
AS customers_email, invoices_1.id 
AS invoices_1_id, invoices_1.custid 
AS invoices_1_custid, invoices_1.invno 
AS invoices_1_invno, invoices_1.amount 
AS invoices_1_amount

FROM customers 
LEFT OUTER JOIN invoices 
AS invoices_1 
ON customers.id = invoices_1.custid

WHERE customers.name = ? ORDER BY invoices_1.id
('Govind Pant',)

OUTER JOIN ha prodotto due righe, ma restituisce un'istanza di Customer. Questo perché Query applica una strategia "univoca", basata sull'identità dell'oggetto, alle entità restituite. È possibile applicare il caricamento desideroso unito senza influire sui risultati della query.

Il subqueryload () è più appropriato per caricare raccolte correlate mentre joinload () è più adatto per relazioni molti-a-uno.