본문으로 건너뛰기
버전: In Development

Expression Filters

Expression 필터를 사용하면 읽기, 쓰기, 쿼리 작업 중에 서버 측에서 record를 필터링할 수 있습니다. 서버가 expression을 평가하고 일치하는 record만 반환(또는 수정)합니다.

서버 요구 사항

Expression 필터는 Aerospike Server 5.2+ 이상이 필요합니다.

Import

from aerospike_py import exp

Overview

Expression은 dict 노드를 반환하는 함수 호출을 조합하여 구성합니다. 이 dict는 filter_expression policy 키를 통해 Rust 레이어로 전달되며, Aerospike 와이어 포맷으로 컴파일됩니다.

# Expression 구성: age >= 21
expr = exp.ge(exp.int_bin("age"), exp.int_val(21))

# policy에서 사용
policy = {"filter_expression": expr}
_, _, bins = client.get(key, policy=policy)

Value Constructors

리터럴 값 expression을 생성합니다:

함수설명
exp.int_val(val)64비트 정수
exp.float_val(val)64비트 실수
exp.string_val(val)문자열
exp.bool_val(val)불리언
exp.blob_val(val)바이트
exp.list_val(val)리스트
exp.map_val(val)Map/dict
exp.geo_val(val)GeoJSON 문자열
exp.nil()Nil 값
exp.infinity()무한대 (범위 제한 없음에 사용)
exp.wildcard()와일드카드 (모든 값과 일치)
exp.int_val(42)
exp.string_val("hello")
exp.bool_val(True)
exp.list_val([1, 2, 3])
exp.map_val({"key": "value"})

Bin Accessors

타입별로 bin 값을 읽습니다:

함수설명
exp.int_bin(name)정수 bin 읽기
exp.float_bin(name)실수 bin 읽기
exp.string_bin(name)문자열 bin 읽기
exp.bool_bin(name)불리언 bin 읽기
exp.blob_bin(name)blob bin 읽기
exp.list_bin(name)list bin 읽기
exp.map_bin(name)map bin 읽기
exp.geo_bin(name)지리공간 bin 읽기
exp.hll_bin(name)HyperLogLog bin 읽기
exp.bin_exists(name)bin이 존재하면 True
exp.bin_type(name)bin 파티클 타입
exp.int_bin("age")
exp.string_bin("name")
exp.bin_exists("optional_field")

Comparison Operations

함수설명
exp.eq(left, right)같음 (==)
exp.ne(left, right)같지 않음 (!=)
exp.gt(left, right)보다 큼 (>)
exp.ge(left, right)크거나 같음 (>=)
exp.lt(left, right)보다 작음 (<)
exp.le(left, right)작거나 같음 (<=)
# age == 30
exp.eq(exp.int_bin("age"), exp.int_val(30))

# score > 100.5
exp.gt(exp.float_bin("score"), exp.float_val(100.5))

# name != "admin"
exp.ne(exp.string_bin("name"), exp.string_val("admin"))

Logical Operations

함수설명
exp.and_(*exprs)논리 AND
exp.or_(*exprs)논리 OR
exp.not_(expr)논리 NOT
exp.xor_(*exprs)논리 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)),
)

# status == "gold" OR status == "platinum"
exp.or_(
exp.eq(exp.string_bin("status"), exp.string_val("gold")),
exp.eq(exp.string_bin("status"), exp.string_val("platinum")),
)

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

Arithmetic Operations

함수설명
exp.num_add(*exprs)덧셈
exp.num_sub(*exprs)뺄셈
exp.num_mul(*exprs)곱셈
exp.num_div(*exprs)나눗셈
exp.num_mod(num, denom)나머지
exp.num_pow(base, exponent)거듭제곱
exp.num_log(num, base)로그
exp.num_abs(value)절댓값
exp.num_floor(num)내림
exp.num_ceil(num)올림
exp.to_int(num)정수로 변환
exp.to_float(num)실수로 변환
exp.min_(*exprs)최솟값
exp.max_(*exprs)최댓값
# (price * quantity) > 1000
exp.gt(
exp.num_mul(exp.int_bin("price"), exp.int_bin("quantity")),
exp.int_val(1000),
)

Integer Bitwise Operations

함수설명
exp.int_and(*exprs)비트 AND
exp.int_or(*exprs)비트 OR
exp.int_xor(*exprs)비트 XOR
exp.int_not(expr)비트 NOT
exp.int_lshift(value, shift)왼쪽 시프트
exp.int_rshift(value, shift)논리 오른쪽 시프트
exp.int_arshift(value, shift)산술 오른쪽 시프트
exp.int_count(expr)비트 수
exp.int_lscan(value, search)MSB에서 스캔
exp.int_rscan(value, search)LSB에서 스캔

Record Metadata

함수설명
exp.key(exp_type)Record 기본 키
exp.key_exists()메타데이터에 key가 저장되어 있으면 True
exp.set_name()Record set 이름
exp.record_size()Record 크기 (바이트, Server 7.0+)
exp.last_update()마지막 업데이트 시간 (에포크 이후 나노초)
exp.since_update()마지막 업데이트 이후 밀리초
exp.void_time()만료 시간 (에포크 이후 나노초)
exp.ttl()Record TTL (초 단위)
exp.is_tombstone()삭제 표시 record이면 True
exp.digest_modulo(mod)다이제스트 모듈로 (샘플링용)
# TTL < 3600 (1시간 이내에 만료)
exp.lt(exp.ttl(), exp.int_val(3600))

# 최근 24시간 이내에 업데이트된 record (86400000 ms)
exp.lt(exp.since_update(), exp.int_val(86_400_000))

# record의 약 10% 샘플링
exp.eq(exp.digest_modulo(10), exp.int_val(0))

Pattern Matching

Regex

# name이 패턴과 일치 (대소문자 무시: flags=2)
exp.regex_compare("^alice.*", 2, exp.string_bin("name"))

Geospatial

# 영역 내의 포인트
region = '{"type":"AeroCircle","coordinates":[[-122.0, 37.5], 1000]}'
exp.geo_compare(exp.geo_bin("location"), exp.geo_val(region))

Variables & Control Flow

Conditional (cond)

# if age < 18: "minor", elif age < 65: "adult", else: "senior"
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 Binding (let_ / def_ / var)

# let total = price * qty in total > 1000
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)),
)

Usage in Operations

Expression 필터는 filter_expression policy 키를 통해 모든 작업에 적용할 수 있습니다.

Get with Filter

expr = exp.ge(exp.int_bin("age"), exp.int_val(21))
try:
_, _, bins = client.get(key, policy={"filter_expression": expr})
except aerospike.FilteredOut:
print("Record does not match filter")

Put with Filter

# status == "active"인 경우에만 업데이트
expr = exp.eq(exp.string_bin("status"), exp.string_val("active"))
client.put(key, {"visits": 1}, policy={"filter_expression": expr})

Query with Filter

# 보조 인덱스 쿼리 + expression 필터
query = client.query("test", "demo")
query.where(aerospike.predicates.between("age", 20, 50))

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

Batch with Filter

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})

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)),
)

query = client.query("test", "users")
records = query.results(policy={"filter_expression": expr})

Records Expiring Soon

# TTL < 1시간인 record
expr = exp.and_(
exp.gt(exp.ttl(), exp.int_val(0)), # 영구 보존이 아닌 record
exp.lt(exp.ttl(), exp.int_val(3600)), # 1시간 이내에 만료
)
query = client.query("test", "cache")
expiring = query.results(policy={"filter_expression": expr})

High-Value Transactions

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