Path expressions
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
This page describes path expressions functionality.
Each operation’s Example shows the code in nine tabs: Aerospike Expression Language (AEL) text on the Java SDK and Python SDK tabs, and the Exp builder on the other seven. See the AEL reference for AEL grammar.
Overview
A path expression is a programmatic, type-safe mechanism used to traverse
and manipulate collection data types (CDTs). Expressions are used by Path
expression operations (selectByPath and modifyByPath) to navigate and
interact with nested Map and
List elements.
Path expressions enhance Aerospike’s capability to retrieve and manipulate data from JSON-like documents. For a tutorial that builds on path expressions with other CDT techniques, see Working with nested collection data types.
The Developer SDK also exposes equivalent path navigation as
Aerospike Expression Language (AEL) text (for example
"$.bookstore.store.book.*[?(@.price < 10.0)]") and as builder-style
allChildrenWithFilter calls.
How path expressions relate to other CDT APIs
Aerospike provides three complementary ways to work with nested collection data.
CDT operations (ListOperation, MapOperation) act in-place on the record,
reading or modifying a single element at a known position. CDT expressions
(list and map) evaluate
to a typed value and can be composed with other expressions for filtering and
computed reads. Path expressions extend both
models by selecting or modifying multiple elements at once using
expression-based contexts such as allChildren() and
allChildrenWithFilter(). For a tutorial that builds on all three techniques,
see
Working with nested collection data types.
Operations
Path expressions use two server-side operations to interact with nested CDTs. Both execute directly on database nodes, minimizing data transfer between client and server.
-
selectByPath: reads and selects multiple nested elements matching the developer-defined paths in a single operation. Returns specific subtrees or values rather than the entire record, reducing network traffic and latency. See the bookstore examples below. -
modifyByPath: removes or updates the value of matched elements, directly on the server.
Navigation and metadata
Navigation through hierarchical CDT structures is managed through a context list (CTX). The list defines element selection and filtering logic at each level of the document.
Path selectors
Paths are defined by progressively applying a list of element selectors from the root bin down to the target element(s). Every step must be contiguous.
-
Index, Key, Rank, Value: standard single-element selectors that navigate to a specific address within a List or Map.
-
allChildren(): matches all elements in a List or Map, enabling multi-element selection and retrieval. See the bookstore examples and advanced usage for worked examples. -
allChildrenWithFilter(exp): matches elements that satisfy a filter expression. See filtering books by price for an example.
Loop variables
During path resolution with allChildrenWithFilter, a typed loop variable
acts as a contextual placeholder that is filled with an aspect of the
current CDT element being evaluated:
MAP_KEY: when the current element is a Map, assign its key to the loop var.VALUE: assign the value of the current (Map or List) element to the loop var.LIST_INDEX: when the current element is a List, assign its index position to the loop var.
For worked examples using loop variables, see the advanced usage page.
Return modes
The selectFlags parameter determines the format and content of the elements
matched by a selectByPath operation.
-
MATCHING_TREE: Returns a hierarchical tree starting from the root down to the target nodes, preserving parent-child relationships. Only branches that satisfied the filter criteria are included. This provides the highest level of structural control. -
VALUE/VALUES: Returns a flat list of values from the final context level. -
MAP_KEY/MAP_KEYS: Returns only the keys of the selected map elements. -
NO_FAIL: Ignores elements with incompatible types rather than failing the entire operation. Useful when matching across heterogeneous collections where not every element has the expected data type.
Indexing and constraints
-
Nesting depth: Lists and Maps support up to 64 levels of nesting (Database 8.2.0 and later). Path expressions can address elements at any of those levels. See Nesting depth limit for how depth is counted.
-
Expression indexes: Path expressions can be combined with expression indexes to support high-speed querying into nested documents. See the expression index example for a walkthrough.
-
Batch inlining: For in-memory namespaces with records exceeding about 1KiB, consider setting
allowInlinetofalse. See performance considerations for details.
Language support
Path expressions are supported in the Java and Python Developer SDKs and in the Java, Python, C#, C, Go, Node.js, and Rust clients. See the client feature compatibility matrix for version details.
Bookstore example
The examples below use the classic JSONPath bookstore dataset
to demonstrate path expression queries. The data is stored as a single map bin named "bookstore".
Data structure
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } }, "expensive": 10}Filtering dimensions
bin "bookstore" (map) ├── store (map) │ ├── book (list of 4 maps) │ │ ├── {category:"reference", author:"Nigel Rees", title:"Sayings of the Century", price:8.95} │ │ ├── {category:"fiction", author:"Evelyn Waugh", title:"Sword of Honour", price:12.99} │ │ ├── {category:"fiction", author:"Herman Melville", title:"Moby Dick", isbn:"0-553-21311-3", price:8.99} │ │ └── {category:"fiction", author:"J. R. R. Tolkien", title:"The Lord of the Rings", isbn:"0-395-19395-8", price:22.99} │ └── bicycle (map) │ ├── color: "red" │ └── price: 19.95 └── expensive: 10- Store level: select
bookvsbicycle(map key navigation) - Book level: filter on
category,author,title,price, presence ofisbn - Cross-level: compare book
priceagainst the top-levelexpensivethreshold (10)
The authors of all books in the store
JSONPath equivalent: $.store.book[*].author
Navigate to the book list, match all children, and select just the "author" key from each book map.
Record record = session.query(key) .bin("authors").selectFrom("$.bookstore.store.book.*.author") .execute() .getFirstRecord();record = ( session.query(key) .bin("authors") .select_from("$.bookstore.store.book.*.author") .first_or_raise() .record)use aerospike::operations::cdt_context::{ctx_all_children, ctx_map_key};use aerospike::operations::path::{self, SelectFlag};use aerospike::{as_val, WritePolicy};
let record = client.operate(&WritePolicy::default(), &key, &[ path::select_by_path("bookstore", SelectFlag::VALUE, [ ctx_map_key(as_val!("store")), ctx_map_key(as_val!("book")), ctx_all_children(), ctx_map_key(as_val!("author")), ]),]).await?;Record record = client.Operate(null, key, CDTOperation.SelectByPath("bookstore", SelectFlag.VALUE, CTX.MapKey(Value.Get("store")), CTX.MapKey(Value.Get("book")), CTX.AllChildren(), CTX.MapKey(Value.Get("author"))));// Requires: import as "github.com/aerospike/aerospike-client-go/v8"record, err := client.Operate(nil, key, as.SelectByPath("bookstore", as.EXP_PATH_SELECT_VALUE, as.CtxMapKey(as.NewStringValue("store")), as.CtxMapKey(as.NewStringValue("book")), as.CtxAllChildren(), as.CtxMapKey(as.NewStringValue("author"))),)const context = new Context() .addMapKey('store') .addMapKey('book') .addAllChildren() .addMapKey('author')
const ops = [ op.selectByPath('bookstore', exp.pathSelectFlags.VALUE, context)]const result = await client.operate(key, ops)as_cdt_ctx ctx;as_cdt_ctx_inita(&ctx, 4);as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("store", false));as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("book", false));as_cdt_ctx_add_all_children(&ctx);as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("author", false));
as_operations ops;as_operations_inita(&ops, 1);as_operations_select_by_path(&err, &ops, "bookstore", &ctx, AS_EXP_PATH_SELECT_VALUE);
as_record* rec = NULL;aerospike_key_operate(&as, &err, NULL, &key, &ops, &rec);Record record = client.operate(null, key, CdtOperation.selectByPath("bookstore", SelectFlags.VALUE, CTX.mapKey(Value.get("store")), CTX.mapKey(Value.get("book")), CTX.allChildren(), CTX.mapKey(Value.get("author"))));ctx = [ cdt_ctx.cdt_ctx_map_key("store"), cdt_ctx.cdt_ctx_map_key("book"), cdt_ctx.cdt_ctx_all_children(), cdt_ctx.cdt_ctx_map_key("author"),]ops = [ operations.select_by_path( bin_name="bookstore", ctx=ctx, flags=aerospike.EXP_PATH_SELECT_VALUE)]_, _, bins = client.operate(key, ops)Output:
["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]Filter all books with an ISBN number
JSONPath equivalent: $.store.book[?(@.isbn)]
Filter books where the isbn key exists using MapReturnType.EXISTS.
Record record = session.query(key) .bin("books").selectFrom("$.bookstore.store.book.*[?(@.isbn.exists())]") .execute() .getFirstRecord();record = ( session.query(key) .bin("books") .select_from("$.bookstore.store.book.*[?(@.isbn.exists())]") .first_or_raise() .record)use aerospike::expressions::{exp_map_loop_var, maps as map_exp, string_val, ExpType, LoopVarPart};use aerospike::operations::cdt_context::{ctx_all_children_with_filter, ctx_map_key};use aerospike::operations::path::{self, SelectFlag};use aerospike::{as_val, MapReturnType, WritePolicy};
let has_isbn = map_exp::get_by_key(MapReturnType::Exists, ExpType::BOOL, string_val("isbn".into()), exp_map_loop_var(LoopVarPart::VALUE), &[]);
let record = client.operate(&WritePolicy::default(), &key, &[ path::select_by_path("bookstore", SelectFlag::VALUE, [ ctx_map_key(as_val!("store")), ctx_map_key(as_val!("book")), ctx_all_children_with_filter(has_isbn), ]),]).await?;Exp hasIsbn = MapExp.GetByKey(MapReturnType.EXISTS, Exp.Type.BOOL, Exp.Val("isbn"), Exp.MapLoopVar(LoopVarPart.VALUE));
Record record = client.Operate(null, key, CDTOperation.SelectByPath("bookstore", SelectFlag.VALUE, CTX.MapKey(Value.Get("store")), CTX.MapKey(Value.Get("book")), CTX.AllChildrenWithFilter(hasIsbn)));// Requires: import as "github.com/aerospike/aerospike-client-go/v8"hasIsbn := as.ExpMapGetByKey( as.MapReturnType.EXISTS, as.ExpTypeBOOL, as.ExpStringVal("isbn"), as.ExpMapLoopVar(as.VALUE),)
record, err := client.Operate(nil, key, as.SelectByPath("bookstore", as.EXP_PATH_SELECT_VALUE, as.CtxMapKey(as.NewStringValue("store")), as.CtxMapKey(as.NewStringValue("book")), as.CtxAllChildrenWithFilter(hasIsbn)),)const hasIsbn = exp.maps.getByKey( exp.loopVarMap(exp.loopVarPart.VALUE), exp.str('isbn'), exp.type.BOOL, maps.returnType.EXISTS)
const context = new Context() .addMapKey('store') .addMapKey('book') .addAllChildrenWithFilter(hasIsbn)
const ops = [ op.selectByPath('bookstore', exp.pathSelectFlags.VALUE, context)]const result = await client.operate(key, ops)as_exp_build(has_isbn, as_exp_map_get_by_key(NULL, AS_MAP_RETURN_EXISTS, AS_EXP_TYPE_BOOL, as_exp_str("isbn"), as_exp_loopvar_map(AS_EXP_LOOPVAR_VALUE)));
as_cdt_ctx ctx;as_cdt_ctx_inita(&ctx, 3);as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("store", false));as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("book", false));as_cdt_ctx_add_all_children_with_filter(&ctx, has_isbn);
as_operations ops;as_operations_inita(&ops, 1);as_operations_select_by_path(&err, &ops, "bookstore", &ctx, AS_EXP_PATH_SELECT_VALUE);
as_record* rec = NULL;aerospike_key_operate(&as, &err, NULL, &key, &ops, &rec);Exp hasIsbn = MapExp.getByKey(MapReturnType.EXISTS, Exp.Type.BOOL, Exp.val("isbn"), Exp.mapLoopVar(LoopVarPart.VALUE));
Record record = client.operate(null, key, CdtOperation.selectByPath("bookstore", SelectFlags.VALUE, CTX.mapKey(Value.get("store")), CTX.mapKey(Value.get("book")), CTX.allChildrenWithFilter(hasIsbn)));has_isbn = exp.MapGetByKey( ctx=None, return_type=aerospike.MAP_RETURN_EXISTS, value_type=exp.ResultType.BOOLEAN, key=exp.Val("isbn"), bin=exp.LoopVarMap(aerospike.EXP_LOOPVAR_VALUE)).compile()
ctx = [ cdt_ctx.cdt_ctx_map_key("store"), cdt_ctx.cdt_ctx_map_key("book"), cdt_ctx.cdt_ctx_all_children_with_filter(has_isbn),]ops = [ operations.select_by_path( bin_name="bookstore", ctx=ctx, flags=aerospike.EXP_PATH_SELECT_VALUE)]_, _, bins = client.operate(key, ops)Output:
[ {"category":"fiction", "author":"Herman Melville", "title":"Moby Dick", "isbn":"0-553-21311-3", "price":8.99}, {"category":"fiction", "author":"J. R. R. Tolkien", "title":"The Lord of the Rings", "isbn":"0-395-19395-8", "price":22.99}]Filter all books cheaper than 10
JSONPath equivalent: $.store.book[?(@.price < 10)]
Record record = session.query(key) .bin("books").selectFrom("$.bookstore.store.book.*[?(@.price < 10.0)]") .execute() .getFirstRecord();record = ( session.query(key) .bin("books") .select_from("$.bookstore.store.book.*[?(@.price < 10.0)]") .first_or_raise() .record)use aerospike::expressions::{exp_map_loop_var, float_val, lt, maps as map_exp, string_val, ExpType, LoopVarPart};use aerospike::operations::cdt_context::{ctx_all_children_with_filter, ctx_map_key};use aerospike::operations::path::{self, SelectFlag};use aerospike::{as_val, MapReturnType, WritePolicy};
let cheap_books = lt( map_exp::get_by_key(MapReturnType::Value, ExpType::FLOAT, string_val("price".into()), exp_map_loop_var(LoopVarPart::VALUE), &[]), float_val(10.0));
let record = client.operate(&WritePolicy::default(), &key, &[ path::select_by_path("bookstore", SelectFlag::VALUE, [ ctx_map_key(as_val!("store")), ctx_map_key(as_val!("book")), ctx_all_children_with_filter(cheap_books), ]),]).await?;Exp cheapBooks = Exp.LT( MapExp.GetByKey(MapReturnType.VALUE, Exp.Type.FLOAT, Exp.Val("price"), Exp.MapLoopVar(LoopVarPart.VALUE)), Exp.Val(10.0));
Record record = client.Operate(null, key, CDTOperation.SelectByPath("bookstore", SelectFlag.VALUE, CTX.MapKey(Value.Get("store")), CTX.MapKey(Value.Get("book")), CTX.AllChildrenWithFilter(cheapBooks)));// Requires: import as "github.com/aerospike/aerospike-client-go/v8"cheapBooks := as.ExpLess( as.ExpMapGetByKey( as.MapReturnType.VALUE, as.ExpTypeFLOAT, as.ExpStringVal("price"), as.ExpMapLoopVar(as.VALUE), ), as.ExpFloatVal(10.0),)
record, err := client.Operate(nil, key, as.SelectByPath("bookstore", as.EXP_PATH_SELECT_VALUE, as.CtxMapKey(as.NewStringValue("store")), as.CtxMapKey(as.NewStringValue("book")), as.CtxAllChildrenWithFilter(cheapBooks)),)const cheapBooks = exp.lt( exp.maps.getByKey( exp.loopVarMap(exp.loopVarPart.VALUE), exp.str('price'), exp.type.FLOAT, maps.returnType.VALUE ), exp.float(10.0))
const context = new Context() .addMapKey('store') .addMapKey('book') .addAllChildrenWithFilter(cheapBooks)
const ops = [ op.selectByPath('bookstore', exp.pathSelectFlags.VALUE, context)]const result = await client.operate(key, ops)as_exp_build(cheap_books, as_exp_cmp_lt( as_exp_map_get_by_key(NULL, AS_MAP_RETURN_VALUE, AS_EXP_TYPE_FLOAT, as_exp_str("price"), as_exp_loopvar_map(AS_EXP_LOOPVAR_VALUE)), as_exp_float(10.0)));
as_cdt_ctx ctx;as_cdt_ctx_inita(&ctx, 3);as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("store", false));as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("book", false));as_cdt_ctx_add_all_children_with_filter(&ctx, cheap_books);
as_operations ops;as_operations_inita(&ops, 1);as_operations_select_by_path(&err, &ops, "bookstore", &ctx, AS_EXP_PATH_SELECT_VALUE);
as_record* rec = NULL;aerospike_key_operate(&as, &err, NULL, &key, &ops, &rec);Exp cheapBooks = Exp.lt( MapExp.getByKey(MapReturnType.VALUE, Exp.Type.FLOAT, Exp.val("price"), Exp.mapLoopVar(LoopVarPart.VALUE)), Exp.val(10.0));
Record record = client.operate(null, key, CdtOperation.selectByPath("bookstore", SelectFlags.VALUE, CTX.mapKey(Value.get("store")), CTX.mapKey(Value.get("book")), CTX.allChildrenWithFilter(cheapBooks)));cheap_books = exp.LT( exp.MapGetByKey( ctx=None, return_type=aerospike.MAP_RETURN_VALUE, value_type=exp.ResultType.FLOAT, key=exp.Val("price"), bin=exp.LoopVarMap(aerospike.EXP_LOOPVAR_VALUE) ), exp.Val(10.0)).compile()
ctx = [ cdt_ctx.cdt_ctx_map_key("store"), cdt_ctx.cdt_ctx_map_key("book"), cdt_ctx.cdt_ctx_all_children_with_filter(cheap_books),]ops = [ operations.select_by_path( bin_name="bookstore", ctx=ctx, flags=aerospike.EXP_PATH_SELECT_VALUE)]_, _, bins = client.operate(key, ops)Output:
[ {"category":"reference", "author":"Nigel Rees", "title":"Sayings of the Century", "price":8.95}, {"category":"fiction", "author":"Herman Melville", "title":"Moby Dick", "isbn":"0-553-21311-3", "price":8.99}]Filter all fiction books costing less than 10
JSONPath equivalent: $.store.book[?(@.category=='fiction' && @.price < 10)]
Compound filter combining two conditions with and().
Record record = session.query(key) .bin("books").selectFrom("$.bookstore.store.book.*[?(@.category == 'fiction' and @.price < 10.0)]") .execute() .getFirstRecord();record = ( session.query(key) .bin("books") .select_from("$.bookstore.store.book.*[?(@.category == 'fiction' and @.price < 10.0)]") .first_or_raise() .record)use aerospike::expressions::{and, eq, exp_map_loop_var, float_val, lt, maps as map_exp, string_val, ExpType, LoopVarPart};use aerospike::operations::cdt_context::{ctx_all_children_with_filter, ctx_map_key};use aerospike::operations::path::{self, SelectFlag};use aerospike::{as_val, MapReturnType, WritePolicy};
let is_fiction = eq( map_exp::get_by_key(MapReturnType::Value, ExpType::STRING, string_val("category".into()), exp_map_loop_var(LoopVarPart::VALUE), &[]), string_val("fiction".into()));
let cheap_books = lt( map_exp::get_by_key(MapReturnType::Value, ExpType::FLOAT, string_val("price".into()), exp_map_loop_var(LoopVarPart::VALUE), &[]), float_val(10.0));
let record = client.operate(&WritePolicy::default(), &key, &[ path::select_by_path("bookstore", SelectFlag::VALUE, [ ctx_map_key(as_val!("store")), ctx_map_key(as_val!("book")), ctx_all_children_with_filter(and(vec![is_fiction, cheap_books])), ]),]).await?;Exp isFiction = Exp.EQ( MapExp.GetByKey(MapReturnType.VALUE, Exp.Type.STRING, Exp.Val("category"), Exp.MapLoopVar(LoopVarPart.VALUE)), Exp.Val("fiction"));
Exp cheapBooks = Exp.LT( MapExp.GetByKey(MapReturnType.VALUE, Exp.Type.FLOAT, Exp.Val("price"), Exp.MapLoopVar(LoopVarPart.VALUE)), Exp.Val(10.0));
Record record = client.Operate(null, key, CDTOperation.SelectByPath("bookstore", SelectFlag.VALUE, CTX.MapKey(Value.Get("store")), CTX.MapKey(Value.Get("book")), CTX.AllChildrenWithFilter(Exp.And(isFiction, cheapBooks))));// Requires: import as "github.com/aerospike/aerospike-client-go/v8"isFiction := as.ExpEq( as.ExpMapGetByKey( as.MapReturnType.VALUE, as.ExpTypeSTRING, as.ExpStringVal("category"), as.ExpMapLoopVar(as.VALUE), ), as.ExpStringVal("fiction"),)
cheapBooks := as.ExpLess( as.ExpMapGetByKey( as.MapReturnType.VALUE, as.ExpTypeFLOAT, as.ExpStringVal("price"), as.ExpMapLoopVar(as.VALUE), ), as.ExpFloatVal(10.0),)
record, err := client.Operate(nil, key, as.SelectByPath("bookstore", as.EXP_PATH_SELECT_VALUE, as.CtxMapKey(as.NewStringValue("store")), as.CtxMapKey(as.NewStringValue("book")), as.CtxAllChildrenWithFilter(as.ExpAnd(isFiction, cheapBooks))),)const isFiction = exp.eq( exp.maps.getByKey( exp.loopVarMap(exp.loopVarPart.VALUE), exp.str('category'), exp.type.STR, maps.returnType.VALUE ), exp.str('fiction'))
const cheapBooks = exp.lt( exp.maps.getByKey( exp.loopVarMap(exp.loopVarPart.VALUE), exp.str('price'), exp.type.FLOAT, maps.returnType.VALUE ), exp.float(10.0))
const context = new Context() .addMapKey('store') .addMapKey('book') .addAllChildrenWithFilter(exp.and(isFiction, cheapBooks))
const ops = [ op.selectByPath('bookstore', exp.pathSelectFlags.VALUE, context)]const result = await client.operate(key, ops)as_exp_build(filter, as_exp_and( as_exp_cmp_eq( as_exp_map_get_by_key(NULL, AS_MAP_RETURN_VALUE, AS_EXP_TYPE_STR, as_exp_str("category"), as_exp_loopvar_map(AS_EXP_LOOPVAR_VALUE)), as_exp_str("fiction")), as_exp_cmp_lt( as_exp_map_get_by_key(NULL, AS_MAP_RETURN_VALUE, AS_EXP_TYPE_FLOAT, as_exp_str("price"), as_exp_loopvar_map(AS_EXP_LOOPVAR_VALUE)), as_exp_float(10.0))));
as_cdt_ctx ctx;as_cdt_ctx_inita(&ctx, 3);as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("store", false));as_cdt_ctx_add_map_key(&ctx, (as_val*)as_string_new("book", false));as_cdt_ctx_add_all_children_with_filter(&ctx, filter);
as_operations ops;as_operations_inita(&ops, 1);as_operations_select_by_path(&err, &ops, "bookstore", &ctx, AS_EXP_PATH_SELECT_VALUE);
as_record* rec = NULL;aerospike_key_operate(&as, &err, NULL, &key, &ops, &rec);Exp isFiction = Exp.eq( MapExp.getByKey(MapReturnType.VALUE, Exp.Type.STRING, Exp.val("category"), Exp.mapLoopVar(LoopVarPart.VALUE)), Exp.val("fiction"));
Exp cheapBooks = Exp.lt( MapExp.getByKey(MapReturnType.VALUE, Exp.Type.FLOAT, Exp.val("price"), Exp.mapLoopVar(LoopVarPart.VALUE)), Exp.val(10.0));
Record record = client.operate(null, key, CdtOperation.selectByPath("bookstore", SelectFlags.VALUE, CTX.mapKey(Value.get("store")), CTX.mapKey(Value.get("book")), CTX.allChildrenWithFilter(Exp.and(isFiction, cheapBooks))));is_fiction = exp.Eq( exp.MapGetByKey( ctx=None, return_type=aerospike.MAP_RETURN_VALUE, value_type=exp.ResultType.STRING, key=exp.Val("category"), bin=exp.LoopVarMap(aerospike.EXP_LOOPVAR_VALUE) ), exp.Val("fiction"))
cheap_books = exp.LT( exp.MapGetByKey( ctx=None, return_type=aerospike.MAP_RETURN_VALUE, value_type=exp.ResultType.FLOAT, key=exp.Val("price"), bin=exp.LoopVarMap(aerospike.EXP_LOOPVAR_VALUE) ), exp.Val(10.0))
combined = exp.And(is_fiction, cheap_books).compile()
ctx = [ cdt_ctx.cdt_ctx_map_key("store"), cdt_ctx.cdt_ctx_map_key("book"), cdt_ctx.cdt_ctx_all_children_with_filter(combined),]ops = [ operations.select_by_path( bin_name="bookstore", ctx=ctx, flags=aerospike.EXP_PATH_SELECT_VALUE)]_, _, bins = client.operate(key, ops)Output:
[ {"category":"fiction", "author":"Herman Melville", "title":"Moby Dick", "isbn":"0-553-21311-3", "price":8.99}]Next steps
-
Check out the Quickstart: Path expressions.
-
Dive deeper with advanced usage.
-
Find more information in the FAQ.