Skip to main content

Expression Filters

Expression filters apply to read, write, and query operations. The server evaluates each expression and returns or modifies only matching records.

Server Requirement

Expression filters require Aerospike Server 5.2+.

Import

from aerospike_py import exp, predicates

Basic Usage

# Build expression: age >= 21
expr = exp.ge(exp.int_bin("age"), exp.int_val(21))

# Use in any operation via policy
record = client.get(key, policy={"filter_expression": expr})

Value Constructors

FunctionDescription
int_val(v)64-bit integer
float_val(v)64-bit float
string_val(v)String
bool_val(v)Boolean
blob_val(v)Bytes
list_val(v)List
map_val(v)Map/dict
geo_val(v)GeoJSON string
nil()Nil
infinity()Infinity (unbounded ranges)
wildcard()Wildcard

Bin Accessors

FunctionDescription
int_bin(name)Integer bin
float_bin(name)Float bin
string_bin(name)String bin
bool_bin(name)Boolean bin
blob_bin(name)Blob bin
list_bin(name)List bin
map_bin(name)Map bin
geo_bin(name)Geospatial bin
hll_bin(name)HyperLogLog bin
bin_exists(name)True if bin exists
bin_type(name)Bin particle type

Comparison

FunctionOperator
eq(l, r)==
ne(l, r)!=
gt(l, r)>
ge(l, r)>=
lt(l, r)<
le(l, r)<=

Logic

FunctionDescription
and_(*exprs)Logical AND
or_(*exprs)Logical OR
not_(expr)Logical NOT
xor_(*exprs)Logical XOR
# age >= 18 AND active == true
exp.and_(
exp.ge(exp.int_bin("age"), exp.int_val(18)),
exp.eq(exp.bool_bin("active"), exp.bool_val(True)),
)

# NOT deleted
exp.not_(exp.eq(exp.bool_bin("deleted"), exp.bool_val(True)))

Numeric Operations

FunctionDescription
num_add, num_sub, num_mul, num_divArithmetic
num_mod, num_pow, num_logModulo, power, log
num_abs, num_floor, num_ceilAbsolute, floor, ceil
to_int, to_floatType conversion
min_, max_Min/max
# (price * quantity) > 1000
exp.gt(
exp.num_mul(exp.int_bin("price"), exp.int_bin("quantity")),
exp.int_val(1000),
)

Record Metadata

FunctionDescription
key(exp_type)Primary key
key_exists()Key stored in metadata?
set_name()Set name
record_size()Size in bytes (Server 7.0+)
last_update()Last update (ns since epoch)
since_update()Ms since last update
void_time()Expiration (ns since epoch)
ttl()TTL in seconds
is_tombstone()Tombstone record?
digest_modulo(mod)Digest modulo (sampling)
# Expiring within 1 hour
exp.lt(exp.ttl(), exp.int_val(3600))

# Sample ~10% of records
exp.eq(exp.digest_modulo(10), exp.int_val(0))

Pattern Matching

# Regex (flags=2 for case insensitive)
exp.regex_compare("^alice.*", 2, exp.string_bin("name"))

# Geospatial: point within circle
region = '{"type":"AeroCircle","coordinates":[[-122.0, 37.5], 1000]}'
exp.geo_compare(exp.geo_bin("location"), exp.geo_val(region))

Variables and Control Flow

# Conditional
exp.cond(
exp.lt(exp.int_bin("age"), exp.int_val(18)), exp.string_val("minor"),
exp.lt(exp.int_bin("age"), exp.int_val(65)), exp.string_val("adult"),
exp.string_val("senior"),
)

# Let bindings
exp.let_(
exp.def_("total", exp.num_mul(exp.int_bin("price"), exp.int_bin("qty"))),
exp.gt(exp.var("total"), exp.int_val(1000)),
)

Using with Operations

Get / Put

expr = exp.ge(exp.int_bin("age"), exp.int_val(21))

# Get: raises FilteredOut if no match
record = client.get(key, policy={"filter_expression": expr})

# Put: only update if status == "active"
expr = exp.eq(exp.string_bin("status"), exp.string_val("active"))
client.put(key, {"visits": 1}, policy={"filter_expression": expr})

Query

query = client.query("test", "demo")
query.where(predicates.between("age", 20, 50))

expr = exp.eq(exp.string_bin("region"), exp.string_val("US"))
records = query.results(policy={"filter_expression": expr})

Batch

expr = exp.ge(exp.int_bin("score"), exp.int_val(100))
ops = [{"op": aerospike.OPERATOR_READ, "bin": "score", "val": None}]
records = client.batch_operate(keys, ops, policy={"filter_expression": expr})

Integer Bitwise Operations

FunctionDescription
int_and(*exprs)Bitwise AND
int_or(*exprs)Bitwise OR
int_xor(*exprs)Bitwise XOR
int_not(expr)Bitwise NOT
int_lshift(value, shift)Left shift
int_rshift(value, shift)Logical right shift
int_arshift(value, shift)Arithmetic right shift
int_count(expr)Bit count (popcount)
int_lscan(value, search)Scan from MSB
int_rscan(value, search)Scan from LSB
# Check if bit 3 is set in flags
exp.ne(
exp.int_and(exp.int_bin("flags"), exp.int_val(0x08)),
exp.int_val(0),
)

# Shift permissions left by 4 bits
exp.int_lshift(exp.int_bin("perms"), exp.int_val(4))

Type Constants

Use EXP_TYPE_* constants with key() and bin_type():

ConstantValueDescription
exp.EXP_TYPE_NIL0Nil
exp.EXP_TYPE_BOOL1Boolean
exp.EXP_TYPE_INT2Integer
exp.EXP_TYPE_STRING3String
exp.EXP_TYPE_LIST4List
exp.EXP_TYPE_MAP5Map
exp.EXP_TYPE_BLOB6Blob (bytes)
exp.EXP_TYPE_FLOAT7Float
exp.EXP_TYPE_GEO8GeoJSON
exp.EXP_TYPE_HLL9HyperLogLog
# Get integer primary key
exp.key(exp.EXP_TYPE_INT)

# Filter records where "data" bin is a list
exp.eq(exp.bin_type("data"), exp.int_val(exp.EXP_TYPE_LIST))

Practical Examples

# Active premium users
expr = exp.and_(
exp.eq(exp.bool_bin("active"), exp.bool_val(True)),
exp.or_(
exp.eq(exp.string_bin("tier"), exp.string_val("gold")),
exp.eq(exp.string_bin("tier"), exp.string_val("platinum")),
),
exp.ge(exp.int_bin("age"), exp.int_val(18)),
)
records = client.query("test", "users").results(policy={"filter_expression": expr})

# Records expiring within 1 hour
expr = exp.and_(
exp.gt(exp.ttl(), exp.int_val(0)),
exp.lt(exp.ttl(), exp.int_val(3600)),
)
expiring = client.query("test", "cache").results(policy={"filter_expression": expr})

# High-value transactions
expr = exp.gt(
exp.num_mul(exp.float_bin("amount"), exp.int_bin("quantity")),
exp.float_val(10000.0),
)
records = client.query("test", "transactions").results(policy={"filter_expression": expr})