Query Builder
O AdonisJs Query Builder fornece uma sintaxe unificada para interagir com bancos de dados SQL usando métodos Javascript. Este guia é uma referência a todos os métodos disponíveis no query builder.
Confira o Database Setup guia para verificar a lista de bancos de dados suportados, opções de configuração e consultas de depuração.
Introdução
Escrever consultas SQL pode ser tedioso de muitas maneiras, mesmo se você for bom com SQL. Vamos imaginar que você escreve todas as suas consultas para MySQL e depois de algum tempo seu gerente pede para você migrar tudo para PostgreSQL. Agora você terá que reescrever/alterar suas consultas MySQL para garantir que elas funcionem bem com PostgreSQL.
Outro problema pode ser a construção de consultas incrementais com blocos condicionais.
// Sem Construtor de Consultas
const sql = 'SELECT * FROM `users`'
if (username) {
sql += ' WHERE `username` = ' + username
}
// Com o Construtor de Consultas
const query = Database.table('users')
if (username) {
query.where('username', username)
}
Exemplo básico
Vamos revisar um exemplo básico de trabalho com o construtor de consultas encadeando métodos diferentes.
const Database = use('Database')
class UserController {
* index (request, response) {
const john = yield Database
.table('users')
.where('username', 'john')
.limit(1)
response.json(john)
}
}
Seleciona
O método select
definirá os campos a serem selecionados para uma determinada consulta SELECT.
yield Database.select('id', 'username').from('users')
// ou
yield Database.select('*').from('users')
# SQL Saída
select `id`, `username` from `users`
select * from `users`
Cláusulas Where
O construtor de consultas oferece vários métodos dinâmicos para adicionar cláusulas where. Além disso, ele oferece suporte a subconsultas passando um closure
em vez do valor real.
OBSERVAÇÃO
Passar undefined
para a cláusula where
causará um erro durante a compilação do SQL. Certifique-se de que os valores dinâmicos não sejam undefined
antes de passá-los.
where(mixed)
const users = yield Database.from('users').where('id', 1)
// Ou
const users = yield Database.from('users').where({ id: 1 })
Além disso, você pode definir o operador de comparação para a cláusula where
.
const adults = yield Database.from('users').where('age', '>', 18)
Você também pode adicionar um retorno de chamada para a cláusula where. O retorno de chamada gera uma consulta SQL um pouco diferente e agrupará todas as cláusulas where dentro de um retorno de chamada.
// Closure
yield Database.from('users').where(function () {
this.where('id', 1)
})
select * from `users` where (`id` = 1)
// Subconsultas
const subquery = Database
.from('accounts')
.where('account_name', 'somename')
.select('account_name')
const users = yield Database
.from('users')
.whereIn('id', subquery)
select * from `users` where `id` in (select `account_name` from `accounts` where `account_name` = 'somename')
whereNot(mixed)
const kids = yield Database.from('users').whereNot('age', '>', 15)
// ou
const users = yield Database.from('users').whereNot({username: 'foo'})
whereIn(mixed)
yield Database.from('users').whereIn('id', [1,2,3])
whereNotIn(mixed)
yield Database.from('users').whereNotIn('id', [1,2,3])
whereNull(mixed)
yield Database.from('users').whereNull('deleted_at')
whereNotNull(mixed)
yield Database.from('users').whereNotNull('created_at')
whereExists(mixed)
yield Database.from('users').whereExists(function () {
this.from('accounts').where('users.id', 'accounts.user_id')
})
whereNotExists(mixed)
yield Database.from('users').whereNotExists(function () {
this.from('accounts').where('users.id', 'accounts.user_id')
})
whereBetween(mixed)
yield Database.table('users').whereBetween('age',[18,32])
whereNotBetween(mixed)
yield Database.table('users').whereNotBetween('age',[45,60])
whereRaw(mixed)
Auxiliar de conveniência para .where(Database.raw(query))
yield Database.from('users').whereRaw('id = ?', [20])
Joins
innerJoin(column, mixed)
yield Database
.table('users')
.innerJoin('accounts', 'user.id', 'accounts.user_id')
Além disso, você pode passar um closure para construir a junção.
yield Database.table('users').innerJoin('accounts', function () {
this
.on('users.id', 'accounts.user_id')
.orOn('users.id', 'accounts.owner_id')
})
Outros métodos de junção:
Método |
---|
leftJoin |
leftOuterJoin |
rightJoin |
rightOuterJoin |
outerJoin |
fullOuterJoin |
crossJoin |
joinRaw |
Ordenação e Limites
distinct(...columns)
yield Database.table('users').distinct('age')
groupBy(...columns)
yield Database.table('users').groupBy('age')
groupByRaw(...columns)
yield Database.table('users').groupByRaw('age, status')
orderBy(column, [direction=asc])
yield Database.table('users').orderBy('id', 'desc')
orderByRaw(column, [direction=asc])
yield Database.table('users').orderByRaw('col NULLS LAST DESC')
having(column, operator, value)
OBSERVAÇÃO
A cláusula groupBy()
é sempre necessária antes de usar o método having()
.
yield Database.table('users').groupBy('age').having('age', '>', 18)
offset/limit(value)
yield Database.table('users').offset(11).limit(10)
Inserções
A operação de inserção retornará o id
da linha inserida. No caso de inserções em massa, o id
do primeiro registro será retornado, e é mais uma limitação do próprio MYSQL. LAST_INSERT_ID.
insert(values)
const userId = yield Database
.table('users')
.insert({username: 'foo', ...})
// INSERÇÃO EM MASSA
const firstUserId = yield Database
.from('users')
.insert([{username: 'foo'}, {username: 'bar'}])
into(tableName)
O método into
é mais legível do que table/from
ao inserir linhas no banco de dados.
const userId = yield Database
.insert({username: 'foo', ...})
.into('users')
Somente PostgreSQL
Para PostgreSQL, você terá que definir a coluna de retorno explicitamente. Todos os outros clientes de banco de dados ignorarão esta instrução.
const userId = yield Database
.insert({ username: 'virk' })
.into('users')
.returning('id')
Atualizações
Todas as operações de atualização retornarão o número de linhas afetadas.
const affectedRows = yield Database
.table('users')
.where('username', 'tutlage')
.update('lastname', 'Virk')
Passe um objeto para várias colunas.
const affectedRows = yield Database
.table('users')
.where('username', 'tutlage')
.update({ lastname: 'Virk', firstname: 'Aman' })
Exclusões
As operações de exclusão também retornarão o número de linhas afetadas.
delete
Além disso, você pode usar del()
, pois delete
é uma palavra-chave reservada em Javascript.
const affectedRows = yield Database
.table('users')
.where('username', 'tutlage')
.delete()
truncate
Truncar removerá todas as linhas de um banco de dados e definirá o ID de incremento automático de volta para 0.
yield Database.truncate('users')
Paginação
O construtor de consultas fornece várias maneiras convenientes de paginar resultados do banco de dados.
forPage(page, [limit=20])
const users = yield Database
.from('users')
.forPage(1, 10)
paginate(page, [limit=20])
const results = yield Database
.from('users')
.paginate(2, 10)
NOTA
A saída do método paginate
é diferente do método forPage
.
// Saída
{
total: 0,
currentPage: 2,
perPage: 10,
lastPage: 0,
data: [{...}]
}
Transações de banco de dados
As transações de banco de dados são operações seguras, que não são refletidas no banco de dados até e a menos que você confirme explicitamente suas alterações.
beginTransaction
O método beginTransaction
retornará o objeto de transação, que pode ser usado para executar quaisquer consultas.
const trx = yield Database.beginTransaction()
yield trx.insert({username: 'virk'}).into('users')
trx.commit() // a consulta de inserção ocorrerá na confirmação
trx.rollback() // não irá inserir nada
transaction
Além disso, você pode encapsular suas transações dentro de um callback. A principal diferença é que você não precisará chamar commit ou
rollback` manualmente se alguma de suas consultas gerar um erro, a transação será revertida automaticamente. Caso contrário, ela será confirmada.
yield Database.transaction(function * (trx) {
yield trx.insert({username: 'virk'}).into('users')
})
Chunks
O método chunk
extrairá registros em pequenos pedaços e executará o closure até que haja resultados. Este método é útil quando você planeja selecionar milhares de registros.
yield Database.from('logs').chunk(200, function (logs) {
console.log(logs)
})
Agregados
count([column])
const total = yield Database.from('users').count()
// CONTAR UMA COLUNA
const total = yield Database.from('users').count('id')
// CONTAR COLUNA COMO NOME
const total = yield Database.from('users').count('id as id')
countDistinct
O countDistinct
é o mesmo que count
, mas adiciona uma expressão distinta.
const total = yield Database.from('users').countDistinct('id')
min(column)
yield Database.from('users').min('age')
yield Database.from('users').min('age as a')
max(column)
yield Database.from('users').max('age')
yield Database.from('users').max('age as a')
sum(column)
yield Database.from('cart').sum('total')
yield Database.from('cart').sum('total as t')
sumDistinct(column)
yield Database.from('cart').sumDistinct('total')
yield Database.from('cart').sumDistinct('total as t')
avg(column)
yield Database.from('users').avg('age')
yield Database.from('users').avg('age as age')
avgDistinct(column)
yield Database.from('users').avgDistinct('age')
yield Database.from('users').avgDistinct('age as age')
increment(column, amount)
Incrementa o valor existente da coluna em 1.
yield Database
.table('credits')
.where('id', 1)
.increment('balance', 10)
decrement(column, amount)
Oposto de increment
.
yield Database
.table('credits')
.where('id', 1)
.decrement('balance', 10)
Auxiliares
pluck(column)
O método pluck
retornará uma matriz de valores para a coluna selecionada.
const usersIds = yield Database.from('users').pluck('id')
pluckAll(...columns)
O método pluckAll
retorna uma matriz de objetos.
NOTA
pluckAll
foi adicionado a partir de adonis-lucid@3.0.12
const usersIds = yield Database.from('users').pluckAll('id')
// ou
const users = yield Database.from('users').pluckAll('id', 'username')
first
O método first
adicionará uma cláusula limit 1 à consulta.
yield Database.from('users').first()
clone
Clone a cadeia de consulta atual para reutilização.
const query = Database
.from('users')
.where('username', 'virk')
.clone()
// depois
yield query
columnInfo([columnName])
Retorna informações para uma determinada coluna.
const username = yield Database.table('users').columnInfo('username')