EctoFlex is a flexible way to query schemas.
It's in very early development and is not yet ready for production use, missing a lot of features that will be added hopefully fairly quickly.
PRs are welcome.
def deps do
[
{:ecto_flex, "~> 0.4.0"}
]
end
This function takes an Ecto.Queryable
, usually an Ecto.Schema
, as the first argument, and a map as a second argument, and returns an Ecto.Query
.
The second argument could take the following form:
%{
"field1" => %{"filter1" => value1},
"field2" => %{"filter2" => value2},
"@association" => %{"assoc_field1" => %{"filter3" => value3}},
}
The map must adhere to the following rules:
@
followed by the association name defined in the schema.Aside from schema fields, EctoFlex treats some keys in a special way. Currently only 1 special key is supported:
flex
flex
key, it looks in the value (a map) for some configurations.%{"flex" => %{"page" => 1, "per_page" => 10, "order" => "name"}}
flex
configurations: page
, per_page
, and order
.%{"order" => "-name"}
Supported filters are:
%{"age" => %{"is" => 35}}
%{"name" => %{"contains" => "tina"}}
%{"birthdate" => %{"greater_than" => yesterday}}
%{"age" => %{"less_than" => 21}}
Filter values could be either a single value or a list. If a list is provided, the values in the list will be OR
d together:
The filter
%{"age" => %{"is" => [20, 21]}}
means: Get me all records with "age" being either 20 or 21.
Assuming we have a %User{}
which has_many :addresses
, we could filter users by address:
%{"@addresses" => %{"city" => %{"is" => "Tokyo"}}}
This filter means: get me all users who have at least one address in Tokyo.
alias EctoFlex.FlexQuery
alias MyApp.Schemas.User
alias MyApp.Repo
conditions = %{ # get me all users
"age" => %{"greater_than" => 20}, # who are older than 20 years old
"email" => %{"contains" => "@gmail.com"}, # who registered with their gmail account
"phone" => %{"not" => nil}, # who have phone numbers on record
"@posts" => %{"inserted_at" => %{"greater_than" => yesterday}}, # who created a post today
"flex" => %{"order" => "-age", "page" => 1, "per_page" => 10}, # the top 10, ordered by age, oldest to youngest.
}
FlexQuery.filter(User, conditions) |> Repo.all()
NOT NULL
. You can now do %{"field" => %{"not" => nil}}
.nil
values. You can now do %{"field" => %{"is" => nil}}
and the query will be constructed properly.