Query Builder: selección y resultados
DB.table("products") crea un RawQueryBuilder nuevo. Model.query() crea un ModelQueryBuilder que comparte sus cláusulas; cambia cómo hidrata, serializa y aplica políticas del modelo. Las cláusulas devuelven el mismo builder y son síncronas: espera únicamente los terminales asíncronos.
Los ejemplos de esta referencia requieren una aplicación iniciada y las tablas products y categories del escenario de testing. Los bloques son funciones de servicio/controlador o consultas que puedes ejecutar dentro de una acción async. Los ejemplos de escritura modifican esas tablas de ejemplo.
No compartas un builder mutable entre peticiones o tareas. El gateway DB sí es compartido: crea un builder para cada consulta y usa clone() para ramificar.
Resultados de tablas y modelos
Sección titulada «Resultados de tablas y modelos»get() devuelve Collection, no una lista Python. Las tablas crudas contienen diccionarios; las consultas de modelo contienen modelos. first() devuelve una fila/modelo o None. value() puede devolver None tanto por ausencia de fila como por un valor NULL. pluck() devuelve una colección de valores. Consulta colecciones y paginación para interpretar sus estructuras.
Para filtrar, unir y escribir continúa con condiciones, joins y escrituras.
Referencia por operación
Sección titulada «Referencia por operación»toPlan()
Sección titulada «toPlan()»toPlan() -> SelectPlanDevuelve el SelectPlan vivo, sin compilar ni ejecutar SQL. Permite inspeccionar filtros, proyección y límites.
Resultado: SelectPlan.
Cambiar el objeto devuelto cambia la consulta; no es un snapshot.
from orionis.support.facades import DB
query = DB.table("products").where("active", True).toPlan()clone()
Sección titulada «clone()»clone() -> SelfCopia las listas del plan para ramificar una consulta. Las cláusulas existentes, la tabla y los planes anidados conservan referencias compartidas; no es una copia profunda.
Resultado: un builder nuevo (Self), con listas de plan copiadas; no ejecuta SQL.
from orionis.support.facades import DB
query = DB.table("products").where("active", True).clone().where("stock", ">", 0)adoptPlan()
Sección titulada «adoptPlan()»adoptPlan(plan: SelectPlan) -> SelfSustituye el plan completo del builder y devuelve la misma instancia. No ejecuta ni valida la existencia de tablas.
| Parámetro | Uso |
|---|---|
plan | SelectPlan que pasa a ser el plan vivo del builder; clónalo antes si necesitas independencia. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
Comparte ese plan: para separarlo usa plan.clone().
from orionis.support.facades import DB
query = DB.table("products").adoptPlan(DB.table("products").where("stock", ">", 0).toPlan())adoptConnection()
Sección titulada «adoptConnection()»adoptConnection(name: str | None) -> SelfSelecciona la conexión de este builder. None vuelve a la predeterminada; no cambia la configuración global.
| Parámetro | Uso |
|---|---|
name | Nombre de conexión o de tabla según el método. La conexión debe estar registrada. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
from orionis.support.facades import DB
query = DB.table("products").adoptConnection("sqlite")select()
Sección titulada «select()»select(*columns: str) -> SelfReemplaza la proyección por las columnas indicadas. select() selecciona todas; las columnas inexistentes fallan al compilar o ejecutar.
| Parámetro | Uso |
|---|---|
columns | Nombres de columnas; pueden estar calificados por tabla o alias. Vacío conserva la selección de todas las columnas. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
from orionis.support.facades import DB
query = DB.table("products").select("id", "name")addSelect()
Sección titulada «addSelect()»addSelect(*columns: str) -> SelfAñade columnas a la proyección actual, conservando las anteriores. No elimina duplicados de nombres.
| Parámetro | Uso |
|---|---|
columns | Nombres de columnas; pueden estar calificados por tabla o alias. Vacío conserva la selección de todas las columnas. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
from orionis.support.facades import DB
query = DB.table("products").select("id").addSelect("name")selectRaw()
Sección titulada «selectRaw()»selectRaw(sql: str, bindings: dict[str, Any] | None=None, alias: str | None=None) -> SelfAñade una expresión SQL confiable y sus bindings. alias permite referenciar el resultado en una tabla derivada.
| Parámetro | Uso |
|---|---|
sql | Fragmento SQL escrito por el desarrollador; los valores variables se pasan mediante bindings. |
bindings | Diccionario de parámetros nombrados :nombre. None equivale a no añadir bindings. |
alias | Alias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
from orionis.support.facades import DB
query = DB.table("products").select("id").selectRaw("price * :factor", {"factor": 2}, alias="double_price")distinct()
Sección titulada «distinct()»distinct() -> SelfSolicita SELECT DISTINCT sobre la proyección completa. No recibe nombres de columnas ni implementa DISTINCT ON.
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
from orionis.support.facades import DB
query = DB.table("products").select("category_id").distinct()orderBy()
Sección titulada «orderBy()»orderBy(column: str, direction: str='asc') -> SelfAñade ordenación ascendente o descendente. Conserva las reglas anteriores; una dirección inválida produce InvalidQueryException.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
direction | asc o desc; se recortan espacios y se normaliza a minúsculas. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
from orionis.support.facades import DB
query = DB.table("products").orderBy("price", "desc").orderBy("id")latest()
Sección titulada «latest()»latest(column: str | None=None) -> SelfOrdena por más recientes primero. Sin columna usa created_at en tablas crudas y el timestamp de creación configurado en modelos.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
No crea la columna; si no existe, indica una columna apropiada.
from orionis.support.facades import DB
query = DB.table("products").latest("id")oldest()
Sección titulada «oldest()»oldest(column: str | None=None) -> SelfOrdena por más antiguos primero. Sin columna usa created_at en tablas crudas y el timestamp de creación configurado en modelos.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
No crea la columna; si no existe, indica una columna apropiada.
from orionis.support.facades import DB
query = DB.table("products").oldest("id")groupBy()
Sección titulada «groupBy()»groupBy(*columns: str) -> SelfAñade columnas de agrupación. Las proyecciones y los agregados deben ser compatibles con GROUP BY en el motor utilizado.
| Parámetro | Uso |
|---|---|
columns | Nombres de columnas; pueden estar calificados por tabla o alias. Vacío conserva la selección de todas las columnas. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
from orionis.support.facades import DB
query = DB.table("products").select("category_id").selectRaw("COUNT(*)", alias="total").groupBy("category_id")limit()
Sección titulada «limit()»limit(value: int) -> SelfEstablece máximo de filas; admite cero. Reemplaza el valor previo de esa opción.
| Parámetro | Uso |
|---|---|
value | Valor de la opción o texto literal del filtro. Los límites/offsets deben ser enteros no negativos y no bool. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
Rechaza negativos, bool y tipos distintos de int con InvalidQueryException.
from orionis.support.facades import DB
query = DB.table("products").orderBy("id").limit(10)take(value: int) -> SelfEstablece máximo de filas (alias de limit); admite cero. Reemplaza el valor previo de esa opción.
| Parámetro | Uso |
|---|---|
value | Valor de la opción o texto literal del filtro. Los límites/offsets deben ser enteros no negativos y no bool. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
Rechaza negativos, bool y tipos distintos de int con InvalidQueryException.
from orionis.support.facades import DB
query = DB.table("products").orderBy("id").take(10)offset()
Sección titulada «offset()»offset(value: int) -> SelfEstablece filas a omitir; admite cero. Reemplaza el valor previo de esa opción.
| Parámetro | Uso |
|---|---|
value | Valor de la opción o texto literal del filtro. Los límites/offsets deben ser enteros no negativos y no bool. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
Rechaza negativos, bool y tipos distintos de int con InvalidQueryException.
from orionis.support.facades import DB
query = DB.table("products").orderBy("id").offset(10)skip(value: int) -> SelfEstablece filas a omitir (alias de offset); admite cero. Reemplaza el valor previo de esa opción.
| Parámetro | Uso |
|---|---|
value | Valor de la opción o texto literal del filtro. Los límites/offsets deben ser enteros no negativos y no bool. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
Rechaza negativos, bool y tipos distintos de int con InvalidQueryException.
from orionis.support.facades import DB
query = DB.table("products").orderBy("id").skip(10)forPage()
Sección titulada «forPage()»forPage(page: int, per_page: int=15) -> SelfConfigura limit=per_page y offset=(page-1)*per_page sin ejecutar consultas.
| Parámetro | Uso |
|---|---|
page | Número de página, entero >=1, sin aceptar bool. |
per_page | Tamaño de página, entero >=1; predeterminado 15. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
Página y tamaño deben ser enteros positivos; no devuelve Paginator.
from orionis.support.facades import DB
query = DB.table("products").orderBy("id").forPage(2, 20)count()
Sección titulada «count()»async count(column: str='*') -> intCuenta filas coincidentes; column=”*” cuenta todas y una columna cuenta sus valores no NULL.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: int.
Los agregados clonan el plan y quitan orden, limit y offset; conservan filtros, grupos, HAVING y uniones. Con GROUP BY, salvo count(""), el terminal escalar devuelve el primer valor calculado, no un resultado por grupo. count("") cuenta las filas del resultado derivado cuando hay grupos, DISTINCT o UNION. Para agregados por grupo usa selectRaw(…).groupBy(…).get(). exists() quita el offset, establece limit=1 y no carga toda la colección.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").where("active", True).count()Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
exists()
Sección titulada «exists()»async exists() -> boolComprueba existencia mediante SELECT limitado a una fila.
Resultado: bool.
Los agregados clonan el plan y quitan orden, limit y offset; conservan filtros, grupos, HAVING y uniones. Con GROUP BY, salvo count(""), el terminal escalar devuelve el primer valor calculado, no un resultado por grupo. count("") cuenta las filas del resultado derivado cuando hay grupos, DISTINCT o UNION. Para agregados por grupo usa selectRaw(…).groupBy(…).get(). exists() quita el offset, establece limit=1 y no carga toda la colección.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").where("active", True).exists()Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
doesntExist()
Sección titulada «doesntExist()»async doesntExist() -> boolInvierte el resultado de exists().
Resultado: bool.
Los agregados clonan el plan y quitan orden, limit y offset; conservan filtros, grupos, HAVING y uniones. Con GROUP BY, salvo count(""), el terminal escalar devuelve el primer valor calculado, no un resultado por grupo. count("") cuenta las filas del resultado derivado cuando hay grupos, DISTINCT o UNION. Para agregados por grupo usa selectRaw(…).groupBy(…).get(). exists() quita el offset, establece limit=1 y no carga toda la colección.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").where("active", True).doesntExist()Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
async max(column: str) -> AnyDevuelve el máximo; sin valores devuelve None.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: Any.
Los agregados clonan el plan y quitan orden, limit y offset; conservan filtros, grupos, HAVING y uniones. Con GROUP BY, salvo count(""), el terminal escalar devuelve el primer valor calculado, no un resultado por grupo. count("") cuenta las filas del resultado derivado cuando hay grupos, DISTINCT o UNION. Para agregados por grupo usa selectRaw(…).groupBy(…).get(). exists() quita el offset, establece limit=1 y no carga toda la colección.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").where("active", True).max("price")Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
async min(column: str) -> AnyDevuelve el mínimo; sin valores devuelve None.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: Any.
Los agregados clonan el plan y quitan orden, limit y offset; conservan filtros, grupos, HAVING y uniones. Con GROUP BY, salvo count(""), el terminal escalar devuelve el primer valor calculado, no un resultado por grupo. count("") cuenta las filas del resultado derivado cuando hay grupos, DISTINCT o UNION. Para agregados por grupo usa selectRaw(…).groupBy(…).get(). exists() quita el offset, establece limit=1 y no carga toda la colección.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").where("active", True).min("price")Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
async avg(column: str) -> float | NoneDevuelve la media convertida a float, o None sin valores.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: float | None.
Los agregados clonan el plan y quitan orden, limit y offset; conservan filtros, grupos, HAVING y uniones. Con GROUP BY, salvo count(""), el terminal escalar devuelve el primer valor calculado, no un resultado por grupo. count("") cuenta las filas del resultado derivado cuando hay grupos, DISTINCT o UNION. Para agregados por grupo usa selectRaw(…).groupBy(…).get(). exists() quita el offset, establece limit=1 y no carga toda la colección.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").where("active", True).avg("price")Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
async sum(column: str) -> AnyDevuelve la suma; sin valores devuelve 0.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: Any.
Los agregados clonan el plan y quitan orden, limit y offset; conservan filtros, grupos, HAVING y uniones. Con GROUP BY, salvo count(""), el terminal escalar devuelve el primer valor calculado, no un resultado por grupo. count("") cuenta las filas del resultado derivado cuando hay grupos, DISTINCT o UNION. Para agregados por grupo usa selectRaw(…).groupBy(…).get(). exists() quita el offset, establece limit=1 y no carga toda la colección.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").where("active", True).sum("price")Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
connection()
Sección titulada «connection()»connection(name: str) -> SelfSelecciona una conexión registrada en este builder sin alterar el gateway DB compartido.
| Parámetro | Uso |
|---|---|
name | Nombre de conexión o de tabla según el método. La conexión debe estar registrada. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
Los terminales requieren una tabla seleccionada y la aplicación iniciada. Los errores de consulta se propagan; paginate necesita enteros positivos y utiliza dos consultas, no una instantánea atómica.
from orionis.support.facades import DB
query = DB.table("products").connection("sqlite")table()
Sección titulada «table()»table(name: str, *, alias: str | None=None) -> SelfReemplaza la tabla y el alias conservando las cláusulas existentes.
| Parámetro | Uso |
|---|---|
name | Nombre de conexión o de tabla según el método. La conexión debe estar registrada. |
alias | Alias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado. |
Resultado: el mismo builder mutable (Self); no ejecuta SQL.
Los terminales requieren una tabla seleccionada y la aplicación iniciada. Los errores de consulta se propagan; paginate necesita enteros positivos y utiliza dos consultas, no una instantánea atómica.
from orionis.support.facades import DB
query = DB.table("products").where("active", True).table("products", alias="p")async get() -> CollectionEjecuta SELECT y devuelve Collection de diccionarios. No hidrata modelos ni aplica sus eventos, scopes o casts.
Resultado: Collection.
Los terminales requieren una tabla seleccionada y la aplicación iniciada. Los errores de consulta se propagan; paginate necesita enteros positivos y utiliza dos consultas, no una instantánea atómica.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").orderBy("id").get()Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
first()
Sección titulada «first()»async first() -> dict[str, Any] | NoneConsulta una copia con limit=1 y devuelve un dict o None, sin cambiar el límite del builder original.
Resultado: dict[str, Any] | None.
Los terminales requieren una tabla seleccionada y la aplicación iniciada. Los errores de consulta se propagan; paginate necesita enteros positivos y utiliza dos consultas, no una instantánea atómica.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").orderBy("id").first()Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
value()
Sección titulada «value()»async value(column: str) -> AnySelecciona una columna en una copia y devuelve su primer valor o None. None también puede ser un valor SQL NULL.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: Any.
Los terminales requieren una tabla seleccionada y la aplicación iniciada. Los errores de consulta se propagan; paginate necesita enteros positivos y utiliza dos consultas, no una instantánea atómica.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").where("id", 1).value("name")Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
pluck()
Sección titulada «pluck()»async pluck(column: str) -> CollectionSelecciona una columna y devuelve una Collection de sus valores, conservando el orden de la consulta.
| Parámetro | Uso |
|---|---|
column | Columna de la operación; en where/having también admite un dict de igualdades o un callback de agrupación. |
Resultado: Collection.
Los terminales requieren una tabla seleccionada y la aplicación iniciada. Los errores de consulta se propagan; paginate necesita enteros positivos y utiliza dos consultas, no una instantánea atómica.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").orderBy("id").pluck("name")Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.
paginate()
Sección titulada «paginate()»async paginate(page: int=1, per_page: int=15) -> PaginatorConfigura la página y ejecuta count seguido de get para construir un Paginator de diccionarios.
| Parámetro | Uso |
|---|---|
page | Número de página, entero >=1, sin aceptar bool. |
per_page | Tamaño de página, entero >=1; predeterminado 15. |
Resultado: Paginator.
Los terminales requieren una tabla seleccionada y la aplicación iniciada. Los errores de consulta se propagan; paginate necesita enteros positivos y utiliza dos consultas, no una instantánea atómica.
from orionis.support.facades import DB
async def run_example(): return await DB.table("products").orderBy("id").paginate(page=1, per_page=15)Errores: QueryException si la compilación o ejecución falla; la capa de conexión sanea el mensaje y suprime la causa encadenada del driver.