FatEcto.Dynamics.FatDynamics (FatEcto v1.1.0)

View Source

Provides functions to build dynamic where conditions for Ecto queries.

This module is designed to construct complex where clauses dynamically using Ecto's dynamic/2 macro. It supports a variety of conditions such as equality, inequality, comparison operators (>, <, >=, <=), IN clauses, LIKE/ILIKE for string matching, and JSONB operations (@>, &&).

Key Features:

  • Dynamic Conditions: Builds where clauses dynamically based on field names, values, and logic types (:and/:or).
  • Binding Support: Supports query bindings for joins or nested queries via the :binding option.
  • JSONB Operations: Provides functions to work with JSONB fields, such as checking containment or overlap.
  • String Matching: Supports LIKE and ILIKE for substring matching, including case-insensitive searches.
  • Range Queries: Allows building conditions for ranges (BETWEEN, IN, etc.).

Usage:

Each function in this module constructs a dynamic expression that can be combined with other dynamics or used directly in an Ecto query. The functions accept the following common parameters:

  • key: The field name (as a string or atom).
  • value: The value to compare against (can be a single value, list, or map depending on the function).
  • opts: Options to control the behavior, such :binding (:last for joins).

Example:

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.field_is_nil_dynamic(:location) iex> inspect(result) "dynamic([c], is_nil(c.location))"

This module is typically used internally by FatEcto to construct queries based on user-provided filters.

Summary

Functions

Builds a dynamic query where any element in an array field matches a substring (case-insensitive).

Builds a dynamic query where a field's value is between two provided values.

Builds a dynamic query where a field's value is between or equal to two provided values.

Builds a dynamic query where a field casted to date is equal to a value.

Builds a dynamic query where a field casted to date is greater than a value.

Builds a dynamic query where a field casted to date is great than or equal to a value.

Builds a dynamic query where a field casted to date is less than a value.

Builds a dynamic query where a field casted to date is less than or equal to a value.

Builds a dynamic query where a JSONB field contains any of the provided values.

Builds a dynamic query where a JSONB field contains a specific value.

Builds a dynamic query where a field is equal to a value.

Builds a dynamic query where field is nil.

Builds dynamic condition for field greater than value.

Builds dynamic condition for field greater than or equal to value.

Builds a dynamic query where a field matches a substring (case-insensitive).

Builds a dynamic query where a field's value is in a provided list.

Builds a dynamic query where a field matches a substring (case-sensitive).

Builds a dynamic query where a field is less than a given value.

Builds dynamic condition for field less than or equal to value.

Builds a dynamic query where a field is not equal to a value.

Functions

array_ilike_dynamic(key, value, opts \\ [])

@spec array_ilike_dynamic(any(), any(), nil | maybe_improper_list() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where any element in an array field matches a substring (case-insensitive).

Parameters

  • key - The field name.
  • value - The substring to match.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.array_ilike_dynamic(:tags, "%elixir%")
iex> inspect(result)
"dynamic([q], fragment(\"EXISTS (SELECT 1 FROM UNNEST(?) as value WHERE value ILIKE ?)\", q.tags, ^\"%elixir%\"))"

between_dynamic(key, values, opts \\ [])

@spec between_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field's value is between two provided values.

Parameters

  • key - The field name.
  • values - A list of two values representing the range.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.between_dynamic(:experience_years, [2, 5])
iex> inspect(result)
"dynamic([q], q.experience_years > ^2 and q.experience_years < ^5)"

between_equal_dynamic(key, values, opts \\ [])

@spec between_equal_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field's value is between or equal to two provided values.

Parameters

  • key - The field name.
  • values - A list of two values representing the range.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.between_equal_dynamic(:experience_years, [2, 5])
iex> inspect(result)
"dynamic([q], q.experience_years >= ^2 and q.experience_years <= ^5)"

cast_to_date_eq_dynamic(key, value, opts \\ [])

@spec cast_to_date_eq_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field casted to date is equal to a value.

Parameters

  • key - The field name to cast into date.
  • value - The value to compare against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.cast_to_date_eq_dynamic(:end_date, ~D[2025-02-08])
iex> inspect(result)
"dynamic([q], fragment(\"?::date\", q.end_date == ^~D[2025-02-08]))"

cast_to_date_gt_dynamic(key, value, opts \\ [])

@spec cast_to_date_gt_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field casted to date is greater than a value.

Parameters

  • key - The field name to cast into date.
  • value - The value to compare against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.cast_to_date_gt_dynamic(:end_date, ~D[2025-02-08])
iex> inspect(result)
"dynamic([q], fragment(\"?::date\", q.end_date > ^~D[2025-02-08]))"

cast_to_date_gte_dynamic(key, value, opts \\ [])

@spec cast_to_date_gte_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field casted to date is great than or equal to a value.

Parameters

  • key - The field name to cast into date.
  • value - The value to compare against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.cast_to_date_gte_dynamic(:end_date, ~D[2025-02-08])
iex> inspect(result)
"dynamic([q], fragment(\"?::date\", q.end_date >= ^~D[2025-02-08]))"

cast_to_date_lt_dynamic(key, value, opts \\ [])

@spec cast_to_date_lt_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field casted to date is less than a value.

Parameters

  • key - The field name to cast into date.
  • value - The value to compare against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.cast_to_date_lt_dynamic(:end_date, ~D[2025-02-08])
iex> inspect(result)
"dynamic([q], fragment(\"?::date\", q.end_date < ^~D[2025-02-08]))"

cast_to_date_lte_dynamic(key, value, opts \\ [])

@spec cast_to_date_lte_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field casted to date is less than or equal to a value.

Parameters

  • key - The field name to cast into date.
  • value - The value to compare against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.cast_to_date_lte_dynamic(:end_date, ~D[2025-02-08])
iex> inspect(result)
"dynamic([q], fragment(\"?::date\", q.end_date <= ^~D[2025-02-08]))"

contains_any_dynamic(key, values, opts \\ [])

@spec contains_any_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a JSONB field contains any of the provided values.

Parameters

  • key - The JSONB field name.
  • values - The values to check for overlap.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.contains_any_dynamic(:tags, ["elixir", "erlang"])
iex> inspect(result)
"dynamic([q], fragment(\"? && ?\", q.tags, ^[\"elixir\", \"erlang\"]))"

contains_dynamic(key, values, opts \\ [])

@spec contains_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a JSONB field contains a specific value.

Parameters

  • key - The JSONB field name.
  • values - The value(s) to check for containment.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.contains_dynamic(:metadata, %{"role" => "admin"})
iex> inspect(result)
"dynamic([q], fragment(\"? @> ?\", q.metadata, ^%{\"role\" => \"admin\"}))"

eq_dynamic(key, value, opts \\ [])

@spec eq_dynamic(any(), any(), nil | keyword() | map()) :: Ecto.Query.dynamic_expr()

Builds a dynamic query where a field is equal to a value.

Parameters

  • key - The field name.
  • value - The value to compare against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.eq_dynamic(:experience_years, 2)
iex> inspect(result)
"dynamic([q], q.experience_years == ^2)"

field_is_nil_dynamic(key, opts \\ [])

@spec field_is_nil_dynamic(any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where field is nil.

Parameters

  • key - Field name.
  • opts - Options for binding. Examples iex> result = Elixir.FatEcto.Dynamics.FatDynamics.field_is_nil_dynamic(:location) iex> inspect(result) "dynamic([c], is_nil(c.location))"

gt_dynamic(key, value, opts \\ [])

@spec gt_dynamic(any(), any(), nil | keyword() | map()) :: Ecto.Query.dynamic_expr()

Builds dynamic condition for field greater than value.

Parameters

  • key - Field name.
  • value - Comparison value or field reference.
  • opts - Options for binding Examples iex> result = Elixir.FatEcto.Dynamics.FatDynamics.gtdynamic(:experience_years, 2, [binding: :last]) iex> inspect(result) "dynamic([, ..., c], c.experience_years > ^2)"

gte_dynamic(key, value, opts \\ [])

@spec gte_dynamic(any(), any(), nil | keyword() | map()) :: Ecto.Query.dynamic_expr()

Builds dynamic condition for field greater than or equal to value.

Parameters

  • key - Field name.
  • value - Comparison value or field reference.
  • opts - Options for binding Examples iex> result = Elixir.FatEcto.Dynamics.FatDynamics.gtedynamic(:experience_years, 2, [binding: :last]) iex> inspect(result) "dynamic([, ..., c], c.experience_years >= ^2)"

ilike_dynamic(key, value, opts \\ [])

@spec ilike_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field matches a substring (case-insensitive).

Parameters

  • key - The field name.
  • value - The substring to match.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.ilike_dynamic(:name, "%john%")
iex> inspect(result)
"dynamic([q], ilike(fragment(\"(?)::TEXT\", q.name), ^\"%john%\"))"

in_dynamic(key, values, opts \\ [])

@spec in_dynamic(any(), any(), nil | keyword() | map()) :: Ecto.Query.dynamic_expr()

Builds a dynamic query where a field's value is in a provided list.

Parameters

  • key - The field name.
  • values - A list of values to match against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.in_dynamic(:experience_years, [2, 5])
iex> inspect(result)
"dynamic([q], q.experience_years in ^[2, 5])"

like_dynamic(key, value, opts \\ [])

@spec like_dynamic(any(), any(), nil | keyword() | map()) :: Ecto.Query.dynamic_expr()

Builds a dynamic query where a field matches a substring (case-sensitive).

Parameters

  • key - The field name.
  • value - The substring to match.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.like_dynamic(:name, "%John%")
iex> inspect(result)
"dynamic([q], like(fragment(\"(?)::TEXT\", q.name), ^\"%John%\"))"

lt_dynamic(key, value, opts \\ [])

@spec lt_dynamic(any(), any(), nil | keyword() | map()) :: Ecto.Query.dynamic_expr()

Builds a dynamic query where a field is less than a given value.

Parameters

  • key - The field name.
  • value - The value to compare against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.lt_dynamic(:experience_years, 2, [binding: :last])
iex> inspect(result)
"dynamic([_, ..., c], c.experience_years < ^2)"

lte_dynamic(key, value, opts \\ [])

@spec lte_dynamic(any(), any(), nil | keyword() | map()) :: Ecto.Query.dynamic_expr()

Builds dynamic condition for field less than or equal to value.

Parameters

  • key - Field name.
  • value - Comparison value or field reference.
  • opts - Options for binding Examples iex> result = Elixir.FatEcto.Dynamics.FatDynamics.lte_dynamic(:experience_years, 2) iex> inspect(result) "dynamic([q], q.experience_years <= ^2)"

not_eq_dynamic(key, value, opts \\ [])

@spec not_eq_dynamic(any(), any(), nil | keyword() | map()) ::
  Ecto.Query.dynamic_expr()

Builds a dynamic query where a field is not equal to a value.

Parameters

  • key - The field name.
  • value - The value to compare against.
  • opts - Options for binding and logic type (:and/:or).

Examples

iex> result = Elixir.FatEcto.Dynamics.FatDynamics.not_eq_dynamic(:experience_years, 2)
iex> inspect(result)
"dynamic([q], q.experience_years != ^2)"