SQLAlchemy ORM - Carga ansiosa
La carga ansiosa reduce el número de consultas. SQLAlchemy ofrece funciones de carga ansiosas invocadas a través de opciones de consulta que dan instrucciones adicionales a la consulta. Estas opciones determinan cómo cargar varios atributos mediante el método Query.options ().
Carga de subconsultas
Queremos que las facturas del cliente se carguen con entusiasmo. La opción orm.subqueryload () proporciona una segunda instrucción SELECT que carga completamente las colecciones asociadas con los resultados recién cargados. El nombre "subconsulta" hace que la instrucción SELECT se construya directamente a través de la consulta reutilizada e incrustada como una subconsulta en un SELECT contra la tabla relacionada.
from sqlalchemy.orm import subqueryload
c1 = session.query(Customer).options(subqueryload(Customer.invoices)).filter_by(name = 'Govind Pant').one()
Esto da como resultado las siguientes dos expresiones 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',)
Para acceder a los datos de dos tablas, podemos usar el siguiente programa:
print (c1.name, c1.address, c1.email)
for x in c1.invoices:
print ("Invoice no : {}, Amount : {}".format(x.invno, x.amount))
El resultado del programa anterior es el siguiente:
Govind Pant Gulmandi Aurangabad [email protected]
Invoice no : 3, Amount : 10000
Invoice no : 4, Amount : 5000
Carga unida
La otra función se llama orm.joinedload (). Esto emite un LEFT OUTER JOIN. El objeto principal, así como el objeto o la colección relacionados, se cargan en un solo paso.
from sqlalchemy.orm import joinedload
c1 = session.query(Customer).options(joinedload(Customer.invoices)).filter_by(name='Govind Pant').one()
Esto emite la siguiente expresión dando la misma salida que la anterior:
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 resultó en dos filas, pero devuelve una instancia de Customer. Esto se debe a que Query aplica una estrategia de "uniquing", basada en la identidad del objeto, a las entidades devueltas. La carga ansiosa unida se puede aplicar sin afectar los resultados de la consulta.
El subqueryload () es más apropiado para cargar colecciones relacionadas mientras que joinload () es más adecuado para la relación de varios a uno.