Search documentation of ash

# View Source Ash.Filter (ash v3.4.30)

The representation of a filter in Ash.

## Security Concerns

If you are using a map with string keys, it is likely that you are parsing input. It is important to note that, instead of passing a filter supplied from an external source directly to `Ash.Query.filter/2`, you should call `Ash.Filter.parse_input/2`. This ensures that the filter only uses public attributes, relationships, aggregates and calculations, honors field policies and any policies on related resources.

## Writing a filter

### Built In Predicates

- `is_nil`
- `==`
- `!=`
- `in`
- `<`
- `>`
- `<=`
- `>=`
- `&&`
- `||`
- `<>`
- `/`
- `-`
- `*`
- `+`
- `equals` (alias for `==`)
- `not_equals` (alias for `!=`)
- `gt` (alias for `>`)
- `lt` (alias for `<`)
- `gte` (alias for `>=`)
- `lte` (alias for `<=`)
- `eq` (alias for `==`)
- `not_eq` (alias for `!=`)
- `less_than` (alias for `<`)
- `greater_than` (alias for `>`)
- `less_than_or_equal` (alias for `<=`)
- `greater_than_or_equal` (alias for `>=`)
- `and` (alias for `&&`)
- `or` (alias for `||`)
- `concat` (alias for `<>`)
- `div` (alias for `/`)
- `minus` (alias for `-`)
- `times` (alias for `*`)
- `plus` (alias for `+`)

### BooleanExpression syntax

The expression syntax ultimately just builds the keyword list style filter, but with lots of conveniences that would be very annoying to do manually.

Examples

    Ash.Query.filter(resource, name == "Zardoz")
    Ash.Query.filter(resource, first_name == "Zar" and last_name == "Doz")
    Ash.Query.filter(resource, first_name == "Zar" and last_name in ["Doz", "Daz"] and high_score > 10)
    Ash.Query.filter(resource, first_name == "Zar" or last_name == "Doz" or (high_score > 10 and high_score < -10))

### Expressions

More complex filters can be built using Ash Expressions.

Examples

    # Filter based on the contents of a string attribute
    Ash.Query.filter(Helpdesk.Support.Ticket, contains(subject, "2"))
    # Filter based on the attribute of a joined relationship:
    Ash.Query.filter(Helpdesk.Support.Ticket, representative.name == ^name)

See the Expressions guide guide for more information.

### Keyword list syntax

A filter is a nested keyword list (with some exceptions, like `true` for everything and `false` for nothing).

The key is the "predicate" (or "condition") and the value is the parameter. You can use `and` and `or` to create nested filters. Data layers can expose custom predicates. Eventually, you will be able to define your own custom predicates, which will be a mechanism for you to attach complex filters supported by the data layer to your queries.

Important In a given keyword list, all predicates are considered to be "ands". So `[or: [first_name: "Tom", last_name: "Bombadil"]]` doesn't mean 'First name == "tom" or last_name == "bombadil"'. To say that, you want to provide a list of filters, like so: `[or: [[first_name: "Tom"], [last_name: "Bombadil"]]]`

Some example filters:

    Ash.Query.filter(resource, [name: "Zardoz"])
    Ash.Query.filter(resource, [first_name: "Zar", last_name: "Doz"])
    Ash.Query.filter(resource, [first_name: "Zar", last_name: [in: ["Doz", "Daz"]], high_score: [greater_than: 10]])
    Ash.Query.filter(resource, [or: [
      [first_name: "Zar"],
      [last_name: "Doz"],
      [or: [
        [high_score: [greater_than: 10]]],
        [high_score: [less_than: -10]]
      ]
    ]])

### Other formats

Maps are also accepted, as are maps with string keys. Technically, a list of `[{"string_key", value}]` would also work.

# Summary

## Types

t()

## Functions

add_to_filter(base, addition, op \\ :and, aggregates \\ %{}, calculations \\ %{}, context \\ %{})
add_to_filter!(base, addition, op \\ :and, aggregates \\ %{}, calculations \\ %{}, context \\ %{})
builtin_functions()
builtin_operators()
builtin_predicate_operators()
builtins()
custom_expression(name, args)
do_hydrate_refs(filter, context)
fetch_simple_equality_predicate(expression, attribute)

Can be used to find a simple equality predicate on an attribute

find(expr, pred, ors? \\ true, ands? \\ true)

Find an expression inside of a filter that matches the provided predicate

find_simple_equality_predicate(expression, attribute)

Can be used to find a simple equality predicate on an attribute

find_value(expr, pred)
flat_map(expression, func)
get_filter(resource, id)

Returns a filter statement that would find a single record based on the input.

get_function(key, resource, public?)
get_operator(key)
get_predicate_function(key, resource, public?)
hydrate_refs(value, context)
list_predicates(expression)
list_refs(expression, no_longer_simple? \\ false, in_an_eq? \\ false, expand_calculations? \\ false, expand_get_path? \\ false)
map(filter, func)
move_exprs_to_relationship_path(refs, path)
move_to_relationship_path(expression, relationship_path)
parse(resource, statement, context \\ %{})

Parses a filter statement

parse!(resource, statement, context \\ %{})

Parses a filter statement

parse_input(resource, statement)

Parses a filter statement, accepting only public attributes/relationships, honoring field policies & related resource policies.

parse_input!(resource, statement)

Parses a filter statement, accepting only public attributes/relationships, honoring field policies & related resource policies, raising on errors.

prefix_refs(expr, path)
put_at_path(value, list)
relationship_paths(filter_or_expression, include_exists? \\ false, with_refs? \\ false, expand_aggregates? \\ false)
run_other_data_layer_filters(domain, resource, filter, tenant)
strict_subset_of(filter, candidate)

Returns true if the second argument is a strict subset (always returns the same or less data) of the first

strict_subset_of?(filter, candidate)
to_simple_filter(map, opts \\ [])

Transform an expression based filter to a simple filter, which is just a list of predicates

update_aggregates(expression, mapper, nested_path \\ [], parent_paths \\ [])
used_aggregates(filter, relationship_path \\ [], return_refs? \\ false)
used_calculations(filter, resource, relationship_path \\ [], calculations \\ %{}, aggregates \\ %{}, return_refs? \\ false)

# Types

Link to this type

# t()

View Source

    @type t() :: %Ash.Filter{expression: term(), resource: term()}

# Functions

Link to this function

# add_to_filter(base, addition, op \\ :and, aggregates \\ %{}, calculations \\ %{}, context \\ %{})

View Source
Link to this function

# add_to_filter!(base, addition, op \\ :and, aggregates \\ %{}, calculations \\ %{}, context \\ %{})

View Source
Link to this function

# builtin_functions()

View Source
Link to this function

# builtin_operators()

View Source
Link to this function

# builtin_predicate_operators()

View Source
Link to this function

# builtins()

View Source
Link to this function

# custom_expression(name, args)

View Source
Link to this function

# do_hydrate_refs(filter, context)

View Source
Link to this function

# fetch_simple_equality_predicate(expression, attribute)

View Source

    @spec fetch_simple_equality_predicate(Ash.Expr.t(), atom()) :: {:ok, term()} | :error

Can be used to find a simple equality predicate on an attribute

Use this when your attribute is configured with `filterable? :simple_equality`, and you want to to find the value that it is being filtered on with (if any).

Link to this function

# find(expr, pred, ors? \\ true, ands? \\ true)

View Source

Find an expression inside of a filter that matches the provided predicate

Link to this function

# find_simple_equality_predicate(expression, attribute)

View Source

Can be used to find a simple equality predicate on an attribute

Prefer `fetch_simple_equality_predicate/2`.

Link to this function

# find_value(expr, pred)

View Source
Link to this function

# flat_map(expression, func)

View Source
Link to this function

# get_filter(resource, id)

View Source

Returns a filter statement that would find a single record based on the input.

For example:

    iex> get_filter(MyApp.Post, 1)
    {:ok, %{id: 1}} #using primary key
    iex> get_filter(MyApp.Post, id: 1)
    {:ok, %{id: 1}} #using primary key
    iex> get_filter(MyApp.Post, author_id: 1, publication_id: 2, first_name: "fred")
    {:ok, %{author_id: 1, publication_id: 1}} # using a unique identity
    iex> get_filter(MyApp.Post, first_name: "fred")
    :error # not enough information

Link to this function

# get_function(key, resource, public?)

View Source
Link to this function

# get_operator(key)

View Source
Link to this function

# get_predicate_function(key, resource, public?)

View Source
Link to this function

# hydrate_refs(value, context)

View Source
Link to this function

# list_predicates(expression)

View Source
Link to this function

# list_refs(expression, no_longer_simple? \\ false, in_an_eq? \\ false, expand_calculations? \\ false, expand_get_path? \\ false)

View Source
Link to this function

# map(filter, func)

View Source
Link to this function

# move_exprs_to_relationship_path(refs, path)

View Source
Link to this function

# move_to_relationship_path(expression, relationship_path)

View Source
Link to this function

# parse(resource, statement, context \\ %{})

View Source

Parses a filter statement

See the module documentation for more information on the supported formats for filter statements.

### Important

If you are trying to validate a filter supplied from an external/untrusted source, be sure to use `parse_input/2` instead! The only difference is that it only accepts filters over public attributes/relationships.

Link to this function

# parse!(resource, statement, context \\ %{})

View Source

Parses a filter statement

See `parse/2` for more

Link to this function

# parse_input(resource, statement)

View Source

Parses a filter statement, accepting only public attributes/relationships, honoring field policies & related resource policies.

See `parse/2` for more

Link to this function

# parse_input!(resource, statement)

View Source

Parses a filter statement, accepting only public attributes/relationships, honoring field policies & related resource policies, raising on errors.

See `parse_input/2` for more

Link to this function

# prefix_refs(expr, path)

View Source
Link to this function

# put_at_path(value, list)

View Source
Link to this function

# relationship_paths(filter_or_expression, include_exists? \\ false, with_refs? \\ false, expand_aggregates? \\ false)

View Source
Link to this function

# run_other_data_layer_filters(domain, resource, filter, tenant)

View Source
Link to this function

# strict_subset_of(filter, candidate)

View Source

Returns true if the second argument is a strict subset (always returns the same or less data) of the first

Link to this function

# strict_subset_of?(filter, candidate)

View Source
Link to this function

# to_simple_filter(map, opts \\ [])

View Source

Transform an expression based filter to a simple filter, which is just a list of predicates

Options:

- `:skip_invalid?` (`boolean/0`) - If an invalid filter expression is reached that can't be used with a simple filter (like an `or` statement, or a non-predicate expression), it will be ignored instead of raising an error. The default value is `false`.

Link to this function

# update_aggregates(expression, mapper, nested_path \\ [], parent_paths \\ [])

View Source
Link to this function

# used_aggregates(filter, relationship_path \\ [], return_refs? \\ false)

View Source
Link to this function

# used_calculations(filter, resource, relationship_path \\ [], calculations \\ %{}, aggregates \\ %{}, return_refs? \\ false)

View Source