Skip to content

AEL functions and terminals

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

Reference page: part of the AEL reference. Covers functions with no collection data type (CDT)-typed receiver, and the terminals that end a path. See Applies to on the overview page for SDK and Database version requirements.

Record metadata functions

All forms are invoked on $ with ().

$.ttl() < 3600 /* expires in < 1 hour */
$.recordSize() > 1024 /* large records */
$.timeSinceLastUpdate() < 7200000 /* updated in last 2 hours */
$.isTombstone() /* deleted records */
$.setName() == 'critical'
$.digestModulo(3) == 0 /* partition sampling */
FunctionReturnsDescription
$.ttl()INTRemaining time-to-live in seconds
$.voidTime()INTAbsolute expiry time in nanoseconds (second resolution); -1 = never expires
$.lastUpdateTime()INTLast update time in nanoseconds since Unix epoch (millisecond resolution)
$.timeSinceLastUpdate()INTTime since last update in milliseconds
$.setName()STRINGRecord’s set name
$.key()INT, STRING, or BLOBRecord primary key; optional :TYPE after ()
$.keyExists()BOOLWhether user key is stored
$.isTombstone()BOOLWhether record is deleted
$.recordSize()INTTotal record size in bytes (introduced Database v7.0.0)
$.deviceSize()INTDevice size in bytes. Deprecated as of Database v8.1.0; use recordSize() instead
$.memorySize()INTMemory size in bytes. Deprecated as of Database v8.1.0; use recordSize() instead
$.digestModulo(n)INTDigest modulo n (unitless; n is a positive integer)

Unlike path-level exists() (see Path read terminals), keyExists() and isTombstone() describe record metadata that is always resolvable. They return plain BOOL rather than TRILEAN and never evaluate to unknown.

In a read, isTombstone() is always false, because a read of a tombstone finds no record. It’s meaningful in Cross Datacenter Replication (XDR) filter expressions and in expressions a write request evaluates, where it’s true if the record was a tombstone.

Chaining a method off a metadata call requires parentheses around the metadata call: ($.ttl()).toString() works, but $.ttl().toString() is a parse error. See Parenthesised expressions.

voidTime() and lastUpdateTime() return nanosecond-scale integers with coarser actual precision (second and millisecond granularity, respectively). timeSinceLastUpdate() returns plain milliseconds.

type() applies only to a bare bin path, meaning $.bin itself rather than a nested path into its contents: $.bin.type(). There is no record-level $.type() on $ alone. exists() is not limited to bare bins — it’s also a general path read terminal usable after any navigation, for example $.profile.email.exists() to test a nested map key.

Standalone functions

Functions with no path receiver (single-argument calls use one positional argument unless noted):

FunctionParametersReturnDescription
abs(x)numericsame as xAbsolute value
ceil(x) / floor(x)FLOATFLOATCeiling / floor
min(a, b, …) / max(a, b, …)numeric varargssame typeMinimum / maximum
countOneBits(x)INTINTPopulation count
findBitLeft(x:, value:) / findBitRight(x:, value:)INT, TRILEANINTScan for bit value scanning left/right. value: — true = find a set bit, false = find a clear bit
log(value:, base:) / pow(base:, exponent:)FLOATFLOATLogarithm / power (named parameters)
exclusive(a, b, …)TRILEAN (varargs)TRILEANExactly one operand true; see Logical operators
ceil($.price) /* round up */
floor($.price) /* round down */
min($.a:INT, $.b, $.c) /* smallest of three bins */
countOneBits($.flags) /* number of set bits */
findBitLeft(x: $.flags, value: true) /* index of the leftmost set bit */
findBitRight(x: $.flags, value: false) /* index of the rightmost clear bit */
log(value: 128.0, base: 2.0) /* 7.0 */
pow(base: 2.0, exponent: 10.0) /* 1024.0 */

GeoJSON

FunctionParametersReturnDescription
geoJson('…')STRING (JSON)GEOConstructs a GEO value from a GeoJSON string literal
geoCompare(a, b)GEO, GEOTRILEANBidirectional spatial containment: true if either value contains, or is contained within, the other. Positional

geoJson’s argument must be a string literal at parse time, for example geoJson('{"type":"Point","coordinates":[-122.4,37.7]}'). Dynamic forms such as geoJson($.str) are not supported.

geoCompare($.loc, geoJson('{"type":"Point","coordinates":[-122.349,47.620]}'))
geoCompare(geoJson('{"type":"AeroCircle","coordinates":[[-122.0,37.4],3000.0]}'), $.loc)

Bins typed as GEO are recognized automatically inside geoCompare(...). Use with a GEO2DSPHERE secondary index on the bin. In Python, write GeoJSON bins with set_to_geo_json(...). The Java Developer SDK’s setToGeoJson(...) is equivalent. For example, .bin("geo").setToGeoJson("{\"type\":\"Point\",\"coordinates\":[-122.4194, 37.7749]}"). See Update records for more information about updating records.

Path read terminals

There is no generic get() function in AEL. End a path after navigation/selectors/iteration with a named terminal to pick an explicit result shape, for example $.mapBin.{@a,b}.getKeyValues() or $.listBin.[0:3].count(). To pin a type instead, use the :TYPE suffix on the path (see Types and type suffixes), for example $.binName:INT. If no terminal is written, implicit get returns matched values (multi-select → flat LIST).

TerminalReturnDescription
(implicit get)scalar or LISTDefault: values at path
getKeys()LISTKeys of matched elements (multi-select required)
getKeyValues()LISTFlat [k,v,k,v,…] — not a MAP
getMaps()MAPKey → value map (key-ordered by default)
getTree()MAPStructure-preserving tree
getIndexes()INT or LISTIndex(es) of matched elements
getRanks()INT or LISTRank(s) of matched elements
count()INTElement count on a single-select LIST/MAP path; match count on multi-select
exists()TRILEANWhether path/value exists
toInt() / toFloat()numericCast path result (STRING or FLOAT → INT; STRING or INT → FLOAT)
type()INTRuntime particle-type code (see particle types) — bare bin only ($.bin.type())

There is no separate getValues() terminal: the implicit get (no terminal written) already returns matched values, so a dedicated values-only terminal would be redundant.

Restrictions:

  • getKeys() / getKeyValues() on a bare single-key navigation without multi-select context is a parse error.
  • getIndexes() / getRanks() / getMaps() are not valid on wildcard, filter, or inner-multi-select paths (deferred), for example $.m.*.x.getRanks().
  • getMaps() requires a leaf map range or list selector; a list-only selector has no keys to return as a map (parse error).
  • type() applies to $.bin only, not nested paths ($.bin.seg.type() is a parse error). exists() accepts both a bare bin ($.bin.exists()) and a nested path ($.bin.seg.exists()).
  • toInt() / toFloat() require the receiver type to be known at parse time. If the bin is not already pinned elsewhere in the expression, attach :INT, :FLOAT, or :STRING on the path before the call, for example $.bin:STRING.toInt() > 12.

Result shapes (multi-select):

TerminalShape
Implicit getFlat list of values
getKeyValues()Flat list of alternating keys and values
getMaps()Single map (key → value)
getTree()Nested map preserving path structure

Path write terminals

Return the modified collection unless noted. Selectors {…} / […] attach to the path before the terminal, for example $.m.{@k}.remove(), not $.m.remove({@k}).

Map writes

FunctionDescription
setTo(value)Upsert key from path navigation
update(value)Update only — fail if key missing
insert(value)Create only — fail if key exists
add(amount)Numeric delta on map value
putItems(items)Bulk upsert from MAP — mirrors setTo
insertItems(items)Bulk create-only from MAP — mirrors insert; fails if any key exists
updateItems(items)Bulk update-only from MAP — mirrors update; fails if any key is missing
remove()Remove matched entries
clear()Clear entire map
$.m:MAP.putItems({a: 1, b: 2}) /* upsert both keys */
$.m:MAP.insertItems({a: 1, b: 2}) /* fails if 'a' or 'b' already exists */
$.m:MAP.updateItems({a: 1, b: 2}) /* fails if 'a' or 'b' is missing */

putItems(), insertItems(), and updateItems() also accept the :NO_FAIL and :PARTIAL postfix flags to tolerate per-key failures instead of failing the whole call; see Postfix flags.

List writes

FunctionDescription
append(value) / appendItems(items)Append element(s)
insert(value) / insertItems(items)Insert at index from path
setTo(value)Overwrite at index
add(amount)Increment at index
remove() / clear()Remove matched elements / clear list
sort()Sort list; optional :DROP_DUPS postfix

List write terminals also accept :ADD_UNIQUE and :NO_FAIL where applicable; see Postfix flags.

Bulk symmetry: map putItems / insertItems / updateItems mirror single-key setTo / insert / update. List appendItems / insertItems mirror append / insert. List setTo / add at a path index mirror map single-key setTo / add (lists have no map-style update).

Path addressing (maps vs. lists): write verbs contain what is being operated on, and the path preceeding the verb contains where it goes. Maps are keyed: the path names one key (or the whole map for bulk); bulk keys and values live in the map argument. Lists are indexed: insert, insertItems, setTo, and add take the index from path navigation (for example $.l.[i].…); the argument holds value(s) only. The index is never a function parameter.

Address in pathPayload in ()
Map single-keykey (for example $.m.k.…)value / amount
Map bulkwhole map ($.m.…)map of keys → values
List at indexindex (for example $.l.[i].…)value / list of values
List bulk appendwhole list ($.l.…)list of values

insertItems overload: same verb, different path shape. $.m.insertItems({…}) is whole-map bulk create (no index leaf); $.l.[0].insertItems([…]) is positional bulk insert at the path index, analogous to $.l.[0].insert(value). appendItems is the list bulk op at container scope (append at end; no index leaf), parallel to map bulk ops on $.m.….

Name disambiguation: append(value) on a LIST receiver appends a list element. String concatenation uses the + operator, not a string method — see Arithmetic.

Path modify and remove

FunctionDescription
modify(expr)Transform each matched element using @; result replaces element
remove()Delete matched elements; no-op if none match

Create-order suffixes: modify() and remove() never accept create-order flags (see Collection create-order suffixes). For absent-path tolerance on those terminals, use :NO_FAIL.

Selector placement: {…} / […] selectors attach to the path before the terminal, for example $.m.{@k}.remove(), not $.m.remove({@k}). Terminal-argument selector forms are not part of AEL; dynamic selection in selectors waits for path-parameter (expr) support (see Parenthesised expressions).

Next steps