Introdução
Sejam bem-vindos, fico imensamente feliz com seu interesse em aprender um pouco mais sobre o Ecto e suas funcionalidades do modulo Ecto.Query
para construir queries SQL
Vamos usar o projeto do post Introdução ao Ecto para brincarmos um pouco com as queries sql.
Recomendo ler o projeto anterior sobre Ecto
para melhor compreensão.
Schemas utilizado para este projeto:
Módulo User
defmodule Ecto4noobs.User do
use Ecto.Schema
import Ecto.Changeset
alias Ecto4noobs.Movie
schema "users" do
field(:name, :string)
field(:email, :string)
field(:age, :integer)
belongs_to(:movie, Movie)
end
end
Módulo Movie
defmodule Ecto4noobs.Movie do
use Ecto.Schema
import Ecto.Changeset
alias Ecto4noobs.User
schema "movies" do
field(:title, :string)
field(:director, :string)
field(:year, :integer)
has_many(:users, User)
end
end
Relação Belongs To/Has Many
Vamos iniciar com dois schemas: User e Movie. Vamos implementar uma relação belongs_to/has_many
entre os dois: Um filme tem vários (has many) usuários e um usuário pertence a (belongs to) um filme.
Schema Belongs To
Belongs To utiliza a chave estrangeira para tornar o filme associado a um usuário disponível quando executamos a consulta.
Schema Has Many
Has Many não adiciona dados ao banco de dados por si só. O que ela faz é utilizar uma chave estrangeira
no schema associado (users).
Listando os filmes
from(m in Movie) |> Repo.all()
Se notarmos, veremos que temos a seguinte mensagem: NotLoadAssociation
. Caso a gente queria listar os usuários
juntamente aos filmes
, apenas essa query
não é o suficiente.
Para carregas as associações, faremos:
query = from(m in Movie, preload: [:users]) |> Repo.all()
Exemplos de query com filtros where:
Buscando os usuários com idade menos que 20.
query = from(u in User, where: u.age < 20)
U
representa uma linha da tabela User
e em seguida a gente passa a condição que queremos filtrar, que no caso queremos filtrar a idade que for menor que 20.
Antes de continuarmos vamos aprender um pouco sobre SQL JOIN
O que é um JOIN?
Bom, o join combina duas tabelas através de alguma chave ou valor comum entre elas.
Existem alguns tipos diferentes de JOIN:
INNER JOIN: É um comando que permite a seleção de informações em diferentes tabelas, desde que a informação em questão seja compartilhada por ambas.
LEFT JOIN: É um comando que retorna todos os registros da tabela à esquerda e os registros correspondentes da tabela à direita.
RIGHT JOIN: Ao contrário do LEFT JOIN, o comando RIGHT JOIN retorna todos os dados encontrados na tabela à direita. Porém, se não tiver dados associados entre as tabelas esquerda e direita, ele retorna valores nulos.
Usando INNER JOIN
query =
from(u in User,
inner_join: m in Movie,
on: u.movie_id == m.id,
select: [m.title, u.name])
Neste exemplo, estamos buscando os filmes e o nome do usuário que cada um recebeu. Para isso, começamos a nossa query na tabela User
, depois fazemos um inner_join
na tabela de filmes
e cujo a condição do ID do filme do usuário é igual ao ID do filme. Por fim, a gente faz a seleção dos campos que queremos mostrar.
Usando LEFT JOIN
query =
from(m in Movie,
left_join: u in User,
on: u.movie_id == m.id,
where: u.name == "Floki O Gato" and m.title == "Um Sonho de Liberdade",
select: [m.title, u.name])
Neste exemplo, buscamos filmes que contém o usuário "Floki O Gato". Para isso, começamos a query na tabela Movie, depois fazemos um left_join
na tabela User
e cujo a condição do ID do filme do usuário é igual ao ID do filme eu busco por usuário "Floki O Gato" onde o titulo do filme é "Um Sonho de Liberdade". Por fim, a gente faz a seleção dos campos que queremos mostrar.
Usando LEFT EXCLUDING JOIN
Filmes que não tiveram nenhum usuário
Usando RIGHT JOIN
query =
from(m in Movie,
right_join: u in User,
on: u.movie_id == m.id,
select: [m.title, u.name])
Neste exemplo, estou buscando os filmes com o usuário que foi recebido.
Usando RIGHT EXCLUDING JOIN
Buscar os filmes com os usuário que cada um recebeu
query =
from(m in Movie,
right_join: u in User,
on: u.movie_id == m.id,
where: not is_nil(u.name),
select: [m.title, u.name])
Fragment
Forma de chamar funções em SQL puro no Ecto
query =
from(m in Movie,
select: fragment("upper(?)", m.title))
Estamos fazendo uma listagem de títulos de filme em uppercase fragment(upper)
que é uma função do Postgres.
OU
title = "O Poderoso Chefão"
query = from(m in Movie,
where: m.title == ^title,
select: fragment("upper(?)", m.title))
Quando queremos colocar um valor de uma variável dentro da querie a gente precisa colocar operador pinar (^)
se não, dará erro de compilação.
LIKE
Forma de busca por campo de texto
title = "O"
query =
from(m in Movie,
where: like(m.title, ^"#{title}%"),
select: fragment("upper(?)", m.title))
Filtrando títulos de filme que começam com a letra O
.
Então, nesse nosso exemplo quero buscar os filmes que começam com O, então eu uso a função do Ecto LIKE
passando o campo de texto que eu quero interpolar e o sinal de pinar, por fim o porcent %
que é para dar match
em qualquer termo.
E é isso! =)
Conclusão
Muito obrigado pela leitura até aqui e espero ter ajudado de alguma forma. Tem alguma sugestão ou encontrou algum problema? por favor deixe-me saber. 💜
Top comments (2)
Incrível 👏
Uma honra receber seu feedback!
Tmj Tiago 💜