json_api_query_builder v1.0.2 JsonApiQueryBuilder.Filter View Source

Filter operations for JsonApiQueryBuilder.

Link to this section Summary

Functions

Applies filter conditions from a parsed JSON-API request to an Ecto.Queryable.t

Extract the first segment of a dotted relationship path

Tests if the given string is a join filter

Tests if the given string is a join preload filter

Tests if the given string is either a join filter or a preload filter

Removes the leading path segment from map keys after grouping has been applied

Link to this section Functions

Link to this function filter(query, params, callback, list) View Source
filter(Ecto.Queryable.t(), map(), function(), [{:relationships, [String.t()]}]) :: Ecto.Queryable.t()

Applies filter conditions from a parsed JSON-API request to an Ecto.Queryable.t.

Each filter condition will be cause the given callback to be invoked with the query, attribute and value.

Relationship Filters

There are two types of relationship filters: join filters and preload filters.

Join filters use a dotted notation, eg: "comments.author.articles", and will be used to filter the primary data using a SQL inner join.

Eg: %{"filter" => %{"author.has_bio" => 1}} can be used to find all articles where the related author has a bio in the database.

Preload filters use a nested notation, eg: %{"author" => %{"has_bio" => 1}}, and will only be used to filter the relationships specified in the include parameter.

Eg: %{"include" => "author", "filter" => %{"author" => %{"has_bio" => 1}}} can be used to find all articles, and include the related authors if they have a bio.

Example

JsonApiQueryBuilder.Filter.filter(
  Article,
  %{"filter" => %{"tag" => "animals", "author.has_bio" => "1", "author.has_image" => "1", "comments" => %{"body" => "Great"}}},
  &apply_filter/3,
  relationships: ["author", "comments"]
)

The example above will cause the apply_filter/3 callback to be invoked twice:

  • apply_filter(query, "tag", "animals")
  • apply_filter(query, "author", %{"filter" => %{"has_bio" => "1", "has_image" => "1"}})

    Where apply_filter would be implemented like:

  def apply_filter(query, "tag", val), do: from(article in query, where: ^val in article.tag_list)
  def apply_filter(query, "author", params) do
    user_query = from(User, select: [:id]) |> User.Query.filter(params)
    from(article in query, join: user in ^subquery(user_query), on: article.user_id == user.id)
  end
Link to this function first_relationship_segment(path) View Source
first_relationship_segment(String.t()) :: String.t()

Extract the first segment of a dotted relationship path.

Example

iex> JsonApiQueryBuilder.Filter.first_relationship_segment("a.b.c")
"a"
Link to this function is_join_filter?(relationships, filter) View Source
is_join_filter?([String.t()], String.t()) :: boolean()

Tests if the given string is a join filter.

Example

iex> JsonApiQueryBuilder.Filter.is_join_filter?(["articles", "comments"], "articles.comments.user")
true
iex> JsonApiQueryBuilder.Filter.is_join_filter?(["articles", "comments"], "comments")
false
iex> JsonApiQueryBuilder.Filter.is_join_filter?(["articles", "comments"], "email")
false
Link to this function is_preload_filter?(relationships, filter) View Source
is_preload_filter?([String.t()], String.t()) :: boolean()

Tests if the given string is a join preload filter.

Example

iex> JsonApiQueryBuilder.Filter.is_preload_filter?(["articles", "comments"], "articles.comments.user")
false
iex> JsonApiQueryBuilder.Filter.is_preload_filter?(["articles", "comments"], "comments")
true
iex> JsonApiQueryBuilder.Filter.is_preload_filter?(["articles", "comments"], "email")
false
Link to this function is_relationship_filter?(relationships, filter) View Source
is_relationship_filter?([String.t()], String.t()) :: boolean()

Tests if the given string is either a join filter or a preload filter

Example

iex> JsonApiQueryBuilder.Filter.is_relationship_filter?(["articles", "comments"], "articles.comments.user")
true
iex> JsonApiQueryBuilder.Filter.is_relationship_filter?(["articles", "comments"], "comments")
true
iex> JsonApiQueryBuilder.Filter.is_relationship_filter?(["articles", "comments"], "email")
false
Link to this function trim_leading_relationship_from_keys(relation, rel_filters) View Source
trim_leading_relationship_from_keys(String.t(), list()) :: {String.t(), map()}

Removes the leading path segment from map keys after grouping has been applied.

Example

iex> JsonApiQueryBuilder.Filter.trim_leading_relationship_from_keys("article", [{"article.tag", "animals"}, {"article.comments.user.name", "joe"}])
{"article", %{"comments.user.name" => "joe", "tag" => "animals"}}