Operações CRUD
Os modelos Lucid facilitam muito a execução de operações CRUD e também definem ganchos de ciclo de vida em torno de cada operação.
Criar
Você pode criar e persistir novos registros no banco de dados usando o método estático create
.
import User from '#models/user'
const user = await User.create({
username: 'virk',
email: 'virk@adonisjs.com',
})
console.log(user.$isPersisted) // true
Além disso, você pode criar e persistir novos registros no banco de dados atribuindo valores à instância do modelo e, em seguida, chamando o método save
.
O método save
executa a consulta INSERT ao persistir a instância do modelo pela primeira vez e executa a consulta UPDATE quando o modelo persiste.
import User from '#models/user'
const user = new User()
// Atribuir nome de usuário e e-mail
user.username = 'virk'
user.email = 'virk@adonisjs.com'
// Inserir no banco de dados
await user.save()
console.log(user.$isPersisted) // true
Além disso, você pode usar o método fill
para definir todos os atributos como uma vez e, em seguida, chamar o método save
.
import User from '#models/user'
const user = new User()
// Atribuir nome de usuário e e-mail usando o método de preenchimento e depois salvar
await user
.fill({ username: 'virk', email: 'virk@adonisjs.com' })
.save()
console.log(user.$isPersisted) // true
createMany
Criar várias instâncias de um modelo e persisti-las no banco de dados. O método createMany
aceita as mesmas opções que o método create
.
NOTA
Uma consulta de inserção é emitida para cada instância do modelo para executar os ganchos do ciclo de vida para cada instância.
const user = await User.createMany([
{
email: 'virk@adonisjs.com',
password: 'secret',
},
{
email: 'romain@adonisjs.com',
password: 'secret',
},
])
Ler
Você pode consultar a tabela do banco de dados usando um dos seguintes métodos estáticos.
all
Buscar todos os usuários do banco de dados. O método retorna uma matriz de instâncias do modelo.
const user = await User.all()
// SQL: SELECT * from "users" ORDER BY "id" DESC;
find
Encontrar um registro usando a chave primária. O método retorna uma instância do modelo ou nulo (quando nenhum registro é encontrado).
const user = await User.find(1)
// SQL: SELECT * from "users" WHERE "id" = 1 LIMIT 1;
findBy
Encontrar um registro por um nome de coluna e seu valor. Semelhante ao método find
, este método também retorna uma instância do modelo ou null
.
const user = await User.findBy('email', 'virk@adonisjs.com')
// SQL: SELECT * from "users" WHERE "email" = 'virk@adonisjs.com' LIMIT 1;
findManyBy
Encontre vários registros por um ou vários nomes de coluna e seu valor. Este método retorna uma matriz de instância de modelo ou uma matriz vazia ([]
).
const users = await User.findManyBy('status', 'active')
// SQL: SELECT * from "users" WHERE "status" = 'active';
const posts = await Post.findManyBy({ status: 'published', userId: 1 })
// SQL: SELECT * from "posts" WHERE "status" = 'published' AND "userId" = 1;
first
Busca o primeiro registro do banco de dados. Retorna null
quando não há registros.
const user = await User.first()
// SQL: SELECT * from "users" LIMIT 1;
Variação orFail
Você também pode usar a variação orFail
para os métodos find. Ela gera uma exceção quando nenhuma linha é encontrada.
const user = await User.findOrFail(1)
const user = await User.firstOrFail()
const user = await User.findByOrFail('email', 'virk@adonisjs.com')
A variação orFail
gerará uma exceção E_ROW_NOT_FOUND
com statusCode 404
.
Usando o construtor de consultas
Os métodos estáticos mencionados acima abrangem os casos de uso comuns para consultar o banco de dados. No entanto, você não está limitado apenas a esses métodos e também pode aproveitar a API do construtor de consultas para fazer consultas SQL avançadas.
NOTA
O ModelQueryBuilder retorna uma matriz de instâncias de modelo e não os objetos JavaScript simples.
Você pode obter uma instância de um construtor de consultas para seu modelo usando o método .query
.
const users = await User
.query()
.where('countryCode', 'IN')
.orWhereNull('countryCode')
Para buscar uma única linha, você pode usar o método .first
. Há também um método firstOrFail
.
const users = await User
.query()
.where('countryCode', 'IN')
.orWhereNull('countryCode')
.first()
Atualizar
A maneira padrão de executar atualizações usando o modelo é consultar o registro e, em seguida, atualizá-lo/persisti-lo no banco de dados.
const user = await User.findOrFail(1)
user.lastLoginAt = DateTime.local() // Luxon dateTime é usado
await user.save()
Além disso, você pode usar o método merge
para definir todos os atributos de uma vez e então chamar o método save
.
await user.merge({ lastLoginAt: DateTime.local() }).save()
Por que não usar a consulta de atualização diretamente?
Outra maneira de atualizar os registros é executar uma atualização usando o construtor de consultas manualmente. Por exemplo
await User.query().where('id', 1).update({ lastLoginAt: new Date() })
No entanto, atualizar registros diretamente não aciona nenhum gancho de modelo e nem atualiza automaticamente os carimbos de data/hora.
Recomendamos não enfatizar muito a consulta extra select
, a menos que esteja lidando com milhões de atualizações por segundo e esteja feliz em deixar os recursos do modelo.
Excluir
Como a operação update
, você primeiro busca no banco de dados e exclui a linha. Por exemplo
const user = await User.findOrFail(1)
await user.delete()
Novamente, para que os ganchos funcionem, o Lucid precisa da instância do modelo primeiro. Se você decidir usar o construtor de consultas diretamente, o modelo não disparará nenhum hook.
No entanto, a abordagem do construtor de consultas diretas pode ajudar a executar exclusões em massa.
await User.query().where('isVerified', false).delete()
Métodos idempotentes
Os modelos vêm com muitos métodos úteis para simplificar a criação de registros, encontrando-os primeiro dentro do banco de dados e executando as consultas de criação/atualização somente quando o registro não existir.
firstOrCreate
Pesquise um registro dentro do banco de dados ou crie um novo (somente quando a pesquisa falhar).
No exemplo a seguir, tentamos pesquisar um usuário com um e-mail, mas persistimos tanto o email
quanto a password
, quando a pesquisa inicial falha. Em outras palavras, o searchPayload
e o savePayload
são mesclados durante a chamada de criação.
import User from '#models/user'
// User.firstOrCreate(searchPayload, savePayload)
await User.firstOrCreate(
{ email: 'virk@adonisjs.com' },
{ password: 'secret' }
)
fetchOrCreateMany
O fetchOrCreateMany
é semelhante ao método firstOrCreate
, mas, em vez disso, você pode criar mais de uma linha. O método precisa de uma chave exclusiva para encontrar as linhas duplicadas e uma matriz de objetos para persistir (se ausentes dentro do banco de dados).
import User from '#models/user'
// User.fetchOrCreateMany(key, arrayOfObjects)
await User.fetchOrCreateMany('email', [
{
email: 'foo@example.com',
username: 'foo',
},
{
email: 'bar@example.com',
username: 'bar',
},
{
email: 'baz@example.com',
username: 'baz',
},
])
updateOrCreate
O updateOrCreate
cria um novo registro ou atualiza o registro existente. Como o método firstOrCreate
, você precisa definir uma carga útil de pesquisa e os atributos para inserir/atualizar.
import User from '#models/user'
// User.updateOrCreate(searchPayload, persistancePayload)
await User.updateOrCreate(
{ email: 'virk@adonisjs.com' },
{ password: 'secret' }
)
updateOrCreateMany
O método updateOrCreateMany
permite sincronizar linhas evitando entradas duplicadas. O método precisa de uma chave exclusiva para encontrar as linhas duplicadas e uma matriz de objetos para persistir/atualizar.
import User from '#models/user'
// User.updateOrCreateMany(key, arrayOfObjects)
await User.updateOrCreateMany('email', [
{
email: 'foo@example.com',
username: 'foo',
},
{
email: 'bar@example.com',
username: 'bar',
},
{
email: 'baz@example.com',
username: 'baz',
},
])
Neste exemplo, usamos o e-mail e o nome de usuário como chaves para encontrar duplicatas. Se uma linha já existir com a mesma combinação de e-mail e nome de usuário, ela será atualizada com os novos valores fornecidos. Caso contrário, uma nova linha será criada com os valores fornecidos.
import User from '#models/user'
// User.updateOrCreateMany(keys, arrayOfObjects)
await User.updateOrCreateMany(['email', 'username'], [
{
email: 'foo@example.com',
username: 'foo',
},
{
email: 'bar@example.com',
username: 'bar',
},
{
email: 'baz@example.com',
username: 'baz',
},
])