EctoFlex v0.4.1 EctoFlex.FlexQuery

This module has only one public-facing function, the filter/2 function.

Link to this section Summary

Functions

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.

Link to this section Functions

Link to this function

filter(queryable, params)

filter(Ecto.Queryable.t(), map()) :: Ecto.Query.t()

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:

  iex> %{
  iex>   "field1" => %{"filter1" => value1},
  iex>   "field2" => %{"filter2" => value2},
  iex>   "@association" => %{"assoc_field1" => %{"filter3" => value3}},
  iex> }

The map must adhere to the following rules:

  1. Keys must be strings.
  2. Keys must map to schema fields, unless they have special meanings to EctoFlex (see below for more).
  3. Values are maps themselves.
  4. Each value map key must be one of the predefined "filters" (see below for more).
  5. Association keys start with @ followed by the association name defined in the schema.
  6. Association key values must adhere to this list (see point 1).

Sepcial Keys

Aside from schema fields, EctoFlex treats some keys in a special way. Currently only 1 special key is supported:

  1. flex

    • When EctoFlex finds the flex key, it looks in the value (a map) for some configurations. For example, the following will get the first 10 records ordered by name ascendingly: %{"flex" => %{"page" => 1, "per_page" => 10, "order" => "name"}}
    • So far, there are only 3 supported flex configurations: page, per_page, and order.
    • To order descendingly, prefix the field name with a minus sign: %{"order" => "-name"}

Filters

Supported filters are:

  1. is: %{"age" => %{"is" => 35}}
  2. contains: %{"name" => %{"contains" => "tina"}}
  3. greater_than: %{"birthdate" => %{"greater_than" => yesterday}}
  4. less_than: %{"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 ORd together: The filter

    %{"age" => %{"is" => [20, 21]}}

    means: Get me all records with "age" being either 20 or 21.

Associations

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.

Complete example

  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
    "@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()