ash v1.24.1 Ash.Query View Source

Utilties around constructing/manipulating ash queries.

Ash queries are used for read actions and side loads, and ultimately map to queries to a resource's data layer.

Queries are run by calling read on an API that contains the resource in question

Examples:

MyApp.Post
|> Query.filter(likes > 10)
|> Query.sort([:title])
|> MyApp.Api.read!()

MyApp.Author
|> Query.aggregate(:published_post_count, :posts, filter: [published: true])
|> Query.sort(published_post_count: :desc)
|> Query.limit(10)
|> MyApp.Api.read!()

MyApp.Author
|> Query.load([:post_count, :comment_count])
|> Query.load(posts: [:comments])
|> MyApp.Api.read!()

Link to this section Summary

Functions

Builds a query from a keyword list.

Return the underlying data layer query for an ash query

Attach a filter statement to the query.

Limit the results returned from the query

Loads named calculations or aggregates on the resource.

Create a new query

Skip the first n records

Sets a specific context key to a specific value

Reverse the sort order of a query.

Set the query's api, and any side loaded query's api

Merge a map of values into the query context

Sort the results based on attributes or aggregates (calculations are not yet supported)

Removes a field from the list of fields to load

Link to this section Types

Specs

t() :: %Ash.Query{
  aggregates: term(),
  api: term(),
  calculations: term(),
  context: term(),
  errors: term(),
  filter: term(),
  limit: term(),
  offset: term(),
  resource: term(),
  side_load: term(),
  sort: term(),
  tenant: term(),
  valid?: term()
}

Link to this section Functions

Link to this function

aggregate(query, name, type, relationship, agg_query \\ nil)

View Source

Specs

aggregate(
  t() | Ash.resource(),
  atom(),
  Ash.aggregate_kind(),
  atom() | [atom()],
  Ash.query() | nil
) :: t()

Adds an aggregation to the query.

Aggregations are made available on the aggregates field of the records returned

The only aggregate available currently is a count aggregate. They filter option accepts either a filter or a keyword list of options to supply to build a limiting query for that aggregate. However, currently only filters are accepted.

Link to this function

build(resource, api \\ nil, keyword)

View Source

Specs

build(Ash.resource(), Ash.api() | nil, Keyword.t()) :: t()

Builds a query from a keyword list.

This is used by certain query constructs like aggregates. It can also be used to manipulate a data structure before passing it to an ash query. It allows for building an entire query struct using only a keyword list.

For example:

Ash.Query.build(MyResource, filter: [name: "fred"], sort: [name: :asc], load: [:foo, :bar], offset: 10)

If you want to use the expression style filters, you can use expr/1. Be sure to require Ash.Query first, or import it. Consider importing only the expr/1 macro if you do that

For example:

import Ash.Query, only: [expr: 1]

Ash.Query.build(Myresource, filter: expr(name == "marge"))
Link to this function

calculate(query, name, module_and_opts, context \\ %{})

View Source

Adds a calculation to the query.

Calculations are made available on the calculations field of the records returned

The module_and_opts argument accepts either a module or a {module, opts}. For more information on what that module should look like, see Ash.Calculation.

More features for calculations, like passing anonymous functions, will be supported in the future.

Link to this function

data_layer_query(ash_query, opts \\ [])

View Source

Return the underlying data layer query for an ash query

Link to this macro

filter(query, filter)

View Source (macro)

Attach a filter statement to the query.

The filter is applied as an "and" to any filters currently on the query. For more information on writing filters, see: Ash.Filter.

Specs

limit(t() | Ash.resource(), nil | integer()) :: t()

Limit the results returned from the query

Specs

load(t() | Ash.resource(), atom() | [atom()] | Keyword.t()) :: t()

Loads named calculations or aggregates on the resource.

Currently, loading attributes has no effects, as all attributes are returned. Before long, we will have the default list to load as the attributes, but if you say load(query, [:attribute1]), that will be the only field filled in. This will let data layers make more intelligent "select" statements as well.

Link to this function

new(resource, api \\ nil)

View Source

Create a new query

Specs

offset(t() | Ash.resource(), nil | integer()) :: t()

Skip the first n records

Link to this function

put_context(query, key, value)

View Source

Specs

put_context(t(), atom(), term()) :: t()

Sets a specific context key to a specific value

See set_context/2 for more information.

Specs

reverse(t()) :: t()

Reverse the sort order of a query.

If the query has no sort, an error is added indicating that.

Set the query's api, and any side loaded query's api

Specs

set_context(t(), map()) :: t()

Merge a map of values into the query context

Not much uses this currently.

Link to this function

set_tenant(query, tenant)

View Source

Specs

set_tenant(t() | Ash.resource(), String.t()) :: t()

Specs

sort(t() | Ash.resource(), Ash.sort()) :: t()

Sort the results based on attributes or aggregates (calculations are not yet supported)

Takes a list of fields to sort on, or a keyword list/mixed keyword list of fields and sort directions. The default sort direction is :asc.

Examples:

Ash.Query.sort(query, [:foo, :bar])

Ash.Query.sort(query, [:foo, bar: :desc])

Ash.Query.sort(query, [foo: :desc, bar: :asc])

Specs

unload(t(), [atom()]) :: t()

Removes a field from the list of fields to load

Specs

unset(Ash.resource() | t(), atom() | [atom()]) :: t()