View Source ActiveMemory.Query (ActiveMemory v0.8.1)

The match/1 macro, for queries that need more than equality.

An attributes map (Store.select(%{department: "sales"})) matches fields for equality. When you need comparisons or boolean logic, match/1 compiles an Elixir expression into an ETS/Mnesia match specification at compile time.

import ActiveMemory.Query

query = match(:department == "sales" or :department == "marketing" and :start_date > last_month)
Store.select(query)

Link to this section Summary

Functions

Build a match query from an expression.

Link to this section Functions

Build a match query from an expression.

Field names are written as atoms — :age, not person.age — and compared against values. The result is passed to one/1, select/2 or withdraw/1.

operators

Operators

Comparison: ==, !=, ===, !==, <, <=, >, >=. Boolean: and, or, not.

match(:age > 30)
match(:cylon? == true)
match(:hair_color == "brown" and :age > 45)
match(:department == "sales" or :department == "marketing")

values-must-be-literals-of-a-supported-type-or-variables

Values must be literals of a supported type, or variables

A value written inline must be an integer, binary or atom (booleans and nil included). Any other literal — a float, a Decimal, a DateTime — raises a FunctionClauseError while the query is being compiled:

match(:radius_km > 1000.0)      # ** (FunctionClauseError) no function clause
                                #    matching in ActiveMemory.Query.reduce/1

Bind it to a variable instead. A variable is evaluated at runtime, so any term works:

cutoff = 1000.0
match(:radius_km > cutoff)      # {:>, :radius_km, 1000.0}

yesterday = DateTime.add(DateTime.utc_now(), -1, :day)
match(:inserted_at > yesterday)

comparisons-use-erlang-term-order

Comparisons use Erlang term order

The generated match spec compares with Erlang's term ordering, which is correct for numbers, binaries and atoms but not for struct based values. A Decimal, DateTime or NaiveDateTime is a map, and maps sort above every number and compare field by field, so match(:gravity > threshold) on a :decimal field will not do what you expect. Filter those in Elixir after reading, or store a comparable representation (an integer of milliseconds, for instance) alongside.

Ordering results has the same caveat handled for you — see the :order_by option documented on ActiveMemory.Store, which does use a value's own compare/2.

what-it-does-not-support

What it does not support

There are no joins, aggregates, subqueries, select projections or group_by. A match query filters records of one table and returns whole structs. For anything else, read and work in Elixir.