View Source Ash.Filter (ash v3.4.23)
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
Functions
Can be used to find a simple equality predicate on an attribute
Find an expression inside of a filter that matches the provided predicate
Can be used to find a simple equality predicate on an attribute
Returns a filter statement that would find a single record based on the input.
Parses a filter statement
Parses a filter statement
Parses a filter statement, accepting only public attributes/relationships, honoring field policies & related resource policies.
Parses a filter statement, accepting only public attributes/relationships, honoring field policies & related resource policies, raising on errors.
Returns true if the second argument is a strict subset (always returns the same or less data) of the first
Transform an expression based filter to a simple filter, which is just a list of predicates
Types
Functions
add_to_filter(base, addition, op \\ :and, aggregates \\ %{}, calculations \\ %{}, context \\ %{})
View Sourceadd_to_filter!(base, addition, op \\ :and, aggregates \\ %{}, calculations \\ %{}, context \\ %{})
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).
Find an expression inside of a filter that matches the provided predicate
Can be used to find a simple equality predicate on an attribute
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
list_refs(expression, no_longer_simple? \\ false, in_an_eq? \\ false, expand_calculations? \\ false, expand_get_path? \\ false)
View SourceParses 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.
Parses a filter statement
See parse/2
for more
Parses a filter statement, accepting only public attributes/relationships, honoring field policies & related resource policies.
See parse/2
for more
Parses a filter statement, accepting only public attributes/relationships, honoring field policies & related resource policies, raising on errors.
See parse_input/2
for more
relationship_paths(filter_or_expression, include_exists? \\ false, with_refs? \\ false, expand_aggregates? \\ false)
View SourceReturns true if the second argument is a strict subset (always returns the same or less data) of the first
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 anor
statement, or a non-predicate expression), it will be ignored instead of raising an error. The default value isfalse
.