Use when querying data with Ecto.Query DSL including where clauses, joins, aggregates, preloading, and query composition. Use for building flexible database queries in Elixir applications.
View on GitHubTheBushidoCollective/han
jutsu-ecto
January 24, 2026
Select agents to install to:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-ecto/skills/ecto-query-patterns/SKILL.md -a claude-code --skill ecto-query-patternsInstallation paths:
.claude/skills/ecto-query-patterns/# Ecto Query Patterns
Master Ecto's powerful Query DSL to build efficient, composable database queries.
This skill covers the query syntax, filtering, joining, aggregation, preloading
associations, and advanced query composition patterns.
## Basic Query with from Macro
```elixir
import Ecto.Query, only: [from: 2]
# Basic query using keyword syntax
query = from u in "users",
where: u.age > 18,
select: u.name
# Execute the query
MyApp.Repo.all(query)
```
Queries are built using the `from/2` macro and only sent to the database when
passed to a `Repo` function like `all/1`, `one/1`, or `get/2`. The keyword syntax
provides a readable way to construct queries.
## Query with Schema Module
```elixir
query = from u in MyApp.User,
where: u.age > 18,
select: u.name
MyApp.Repo.all(query)
```
Using a schema module instead of a table name string provides better type safety
and allows Ecto to use the schema's field definitions for validation and casting.
## Bindingless Query Construction
```elixir
from MyApp.Post,
where: [category: "fresh and new"],
order_by: [desc: :published_at],
select: [:id, :title, :body]
```
Bindingless syntax allows building queries without explicit variable bindings.
This works well for simple queries and when using keyword list syntax for conditions.
## Query with Explicit Bindings
```elixir
query = from p in MyApp.Post,
where: p.category == "fresh and new",
order_by: [desc: p.published_at],
select: struct(p, [:id, :title, :body])
MyApp.Repo.all(query)
```
Explicit bindings (like `p` for posts) allow for more complex conditions and
selections. The `struct/2` function selects only specific fields from the schema.
## Dynamic Query Variables
```elixir
category = "fresh and new"
order_by = [desc: :published_at]
select_fields = [:id, :title, :body]
query = from MyApp.Post,
where: [category: ^category],
order_by: ^order_by,
select: ^sele