Most simple FLWORs are path expressions in disguise, and good processors rewrite them. Use predicates for filters that belong to one step, FLWOR for joins, grouping, sorting and anything that needs a variable, and declare function in the query prolog for logic you use twice. One trap is where a positional predicate applies:
(: A declared function used in predicates, and where a positional predicate applies :)
declare function local:price($b as element(book)) as xs:decimal {
xs:decimal($b/supply/price)
};
"FLWOR then [1]: " || (for $b in //book order by local:price($b) return $b/title)[1],
"[1] inside return: " || count(for $b in //book order by local:price($b) return $b/title[1]),
"path with predicates: "
|| string-join(//book[local:price(.) gt 20][subject ne "Cooking"]/@id, " ")xquery -s:booknest-catalog.xml cheapest.xq
q='for $b in //book where $b/identifier = "BN-0003" return $b/title/string()'
basex -i booknest-catalog.xml "$q"; echo
basex -V -i booknest-catalog.xml "$q" | grep -A1 "Optimized Query"Output
"FLWOR then [1]: The Quiet Harbor"
"[1] inside return: 6"
"path with predicates: b2 b6"
Salt and Saffron
Optimized Query:
db:text("booknest-catalog", "BN-0003")/parent::identifier/parent::book/title ! string()[1] after the parenthesized FLWOR picks the cheapest title; [1] inside return applies to each book's own title children, so all six survive. BaseX 693,830 's -V shows the optimizer turning the FLWOR into a path, then using its text index to jump straight to the text "BN-0003" instead of scanning every book.