expr()The expr() function creates type-safe SurrealQL expressions using standalone operator functions, providing an alternative to writing raw SurrealQL strings.
Import:
import { expr , eq , eeq , ne , gt , gte , lt , lte , and , or , not , contains , containsAny , containsAll , containsNone , inside , outside , intersects , matches , knn , add , sub , mul , div , raw } from 'surrealdb' ; Source: utils/expr.ts
Function Signature function expr ( expression : ExprLike ) : BoundQuery Parameters Parameter Type Description expression ExprLikeAn expression created using operator functions.
Returns BoundQuery - Compiled query with bindings
Comparison Operators eq(field, value)Equality comparison (=).
const adults = expr ( eq ( 'age' , 18 ) ) ; await db . select ( new Table ( 'users' ) ) . where ( adults ) ; // WHERE age = 18
eeq(field, value)Exact equality comparison (==).
const exact = expr ( eeq ( 'count' , 0 ) ) ; // WHERE count == 0
ne(field, value)Not equal comparison (!=).
const notAdmin = expr ( ne ( 'role' , 'admin' ) ) ; // WHERE role != 'admin'
gt(field, value), gte(field, value)Greater than (>) and greater than or equal (>=).
const adults = expr ( gt ( 'age' , 17 ) ) ; const adultsInclusive = expr ( gte ( 'age' , 18 ) ) ;
lt(field, value), lte(field, value)Less than (<) and less than or equal (<=).
const young = expr ( lt ( 'age' , 30 ) ) ; const youngInclusive = expr ( lte ( 'age' , 29 ) ) ; Logical Operators and(...conditions)Logical AND - all conditions must be true.
const premiumAdults = expr ( and ( eq ( 'tier' , 'premium' ) , gte ( 'age' , 18 ) ) ) ; // WHERE tier = 'premium' AND age >= 18
or(...conditions)Logical OR - at least one condition must be true.
const adminOrModerator = expr ( or ( eq ( 'role' , 'admin' ) , eq ( 'role' , 'moderator' ) ) ) ; // WHERE role = 'admin' OR role = 'moderator'
not(condition)Logical NOT - inverts the condition.
const notBanned = expr ( not ( eq ( 'status' , 'banned' ) ) ) ; // WHERE NOT status = 'banned' String/Array Operators contains(field, value)Check if field contains value (CONTAINS).
const hasTag = expr ( contains ( 'tags' , 'featured' ) ) ; // WHERE tags CONTAINS 'featured'
containsAny(field, values)Check if field contains any of the values (CONTAINSANY).
const hasAnyTag = expr ( containsAny ( 'tags' , [ 'new' , 'featured' , 'trending' ] ) ) ; // WHERE tags CONTAINSANY ['new', 'featured', 'trending']
containsAll(field, values)Check if field contains all values (CONTAINSALL).
const hasAllTags = expr ( containsAll ( 'tags' , [ 'verified' , 'premium' ] ) ) ; // WHERE tags CONTAINSALL ['verified', 'premium']
containsNone(field, values)Check if field contains none of the values (CONTAINSNONE).
const noBadTags = expr ( containsNone ( 'tags' , [ 'spam' , 'banned' ] ) ) ; // WHERE tags CONTAINSNONE ['spam', 'banned'] Geometry Operators inside(field, geometry)Check if geometry is inside another (INSIDE).
const inRegion = expr ( inside ( 'location' , regionPolygon ) ) ; // WHERE location INSIDE $regionPolygon
outside(field, geometry)Check if geometry is outside another (OUTSIDE).
const outsideZone = expr ( outside ( 'location' , restrictedZone ) ) ; // WHERE location OUTSIDE $restrictedZone
intersects(field, geometry)Check if geometries intersect (INTERSECTS).
const overlaps = expr ( intersects ( 'area' , otherArea ) ) ; // WHERE area INTERSECTS $otherArea Search Operators matches(field, query, ref?)Full-text search match (@@ or @ref@).
// Basic match const searchResults = expr ( matches ( 'content' , 'searchTerm' ) ) ; // WHERE content @@ 'searchTerm' // With reference number const searchWithRef = expr ( matches ( 'content' , 'searchTerm' , 1 ) ) ; // WHERE content @1@ 'searchTerm'
knn(field, vector, k, distance?)K-nearest neighbors vector search.
const similar = expr ( knn ( 'embedding' , [ 0.1 , 0.2 , 0.3 ] , 10 , 'cosine' ) ) ; // WHERE embedding <|10,COSINE|> [0.1, 0.2, 0.3] Arithmetic Operators add(a, b)Addition (+).
const totalPrice = expr ( add ( 'price' , 'tax' ) ) ; // price + tax
sub(a, b)Subtraction (-).
const discount = expr ( sub ( 'original_price' , 'sale_price' ) ) ; // original_price - sale_price
mul(a, b)Multiplication (*).
const total = expr ( mul ( 'price' , 'quantity' ) ) ; // price * quantity
div(a, b)Division (/).
const average = expr ( div ( 'total' , 'count' ) ) ; // total / count Raw Expressions raw(sql)Create raw SurrealQL expressions.
Only use raw() when no other operator is applicable. Incorrect use risks SQL injection.
const custom = expr ( raw ( 'custom_function()' ) ) ; Complete Examples Basic Filtering import { expr , eq , gte } from 'surrealdb' ; // Single condition const active = expr ( eq ( 'status' , 'active' ) ) ; const users = await db . select ( new Table ( 'users' ) ) . where ( active ) ; // Multiple conditions with AND const premiumAdults = expr ( and ( eq ( 'tier' , 'premium' ) , gte ( 'age' , 18 ) , eq ( 'active' , true ) ) ) ; const results = await db . select ( new Table ( 'users' ) ) . where ( premiumAdults ) ; Complex Conditions // Nested OR and AND const eligibleUsers = expr ( or ( and ( eq ( 'tier' , 'premium' ) , gte ( 'age' , 18 ) ) , and ( eq ( 'role' , 'admin' ) , eq ( 'verified' , true ) ) ) ) ; const users = await db . select ( new Table ( 'users' ) ) . where ( eligibleUsers ) ; Date Filtering import { DateTime , Duration } from 'surrealdb' ; const cutoffDate = DateTime . now ( ) . minus ( Duration . parse ( '30d' ) ) ; const recentUsers = expr ( gte ( 'created_at' , cutoffDate ) ) ; const users = await db . select ( new Table ( 'users' ) ) . where ( recentUsers ) ; Array Operations // Check if user has specific tags const hasFeaturedTag = expr ( contains ( 'tags' , 'featured' ) ) ; // Check if has any of these tags const hasPromotedTags = expr ( containsAny ( 'tags' , [ 'featured' , 'trending' , 'new' ] ) ) ; // Must have all required tags const fullyVerified = expr ( containsAll ( 'badges' , [ 'email-verified' , 'phone-verified' ] ) ) ; // Must not have any bad tags const cleanContent = expr ( containsNone ( 'flags' , [ 'spam' , 'inappropriate' ] ) ) ; Geospatial Queries import { GeometryPoint } from 'surrealdb' ; const searchArea = new GeometryPolygon ( [ /* ... */ ] ) ; // Find locations inside area const nearby = expr ( inside ( 'location' , searchArea ) ) ; const locations = await db . select ( new Table ( 'stores' ) ) . where ( nearby ) ; // Find areas that intersect const overlapping = expr ( intersects ( 'coverage_area' , searchArea ) ) ; const zones = await db . select ( new Table ( 'zones' ) ) . where ( overlapping ) ; Full-Text Search // Basic text search const searchQuery = 'javascript tutorial' ; const articles = await db . select ( new Table ( 'articles' ) ) . where ( expr ( matches ( 'content' , searchQuery ) ) ) ; // With reference number for multi-field search const multiField = expr ( or ( matches ( 'title' , searchQuery , 1 ) , matches ( 'content' , searchQuery , 1 ) ) ) ; Vector Search // Find similar items using KNN const queryVector = [ 0.1 , 0.2 , 0.3 , /* ... */ ] ; const similar = expr ( knn ( 'embedding' , queryVector , 10 , 'cosine' ) ) ; const results = await db . select ( new Table ( 'items' ) ) . where ( similar ) ; Reusable Expressions // Define reusable filters const activeFilter = expr ( eq ( 'active' , true ) ) ; const verifiedFilter = expr ( eq ( 'verified' , true ) ) ; const premiumFilter = expr ( eq ( 'tier' , 'premium' ) ) ; // Combine as needed const premiumActive = expr ( and ( activeFilter , premiumFilter ) ) ; const verifiedActive = expr ( and ( activeFilter , verifiedFilter ) ) ; // Use in queries const users1 = await db . select ( new Table ( 'users' ) ) . where ( premiumActive ) ; const users2 = await db . select ( new Table ( 'users' ) ) . where ( verifiedActive ) ; Update with Expressions const condition = expr ( and ( eq ( 'status' , 'pending' ) , lt ( 'created_at' , DateTime . now ( ) . minus ( Duration . parse ( '1h' ) ) ) ) ) ; const updated = await db . update ( new Table ( 'orders' ) ) . merge ( { status : 'expired' } ) . where ( condition ) ; Delete with Expressions const oldInactive = expr ( and ( eq ( 'active' , false ) , lt ( 'last_login' , DateTime . now ( ) . minus ( Duration . parse ( '90d' ) ) ) ) ) ; const deleted = await db . delete ( new Table ( 'users' ) ) . where ( oldInactive ) ; Best Practices 1. Use Expressions for Complex Conditions // Good: Type-safe and reusable const condition = expr ( and ( gte ( 'age' , 18 ) , eq ( 'verified' , true ) ) ) ; // Avoid: Raw strings (no type safety) const condition = 'age >= 18 AND verified = true' ; 2. Build Expressions Compositionally // Good: Compose small expressions const isAdult = expr ( gte ( 'age' , 18 ) ) ; const isVerified = expr ( eq ( 'verified' , true ) ) ; const isActive = expr ( eq ( 'active' , true ) ) ; const eligibleUsers = expr ( and ( isAdult , isVerified , isActive ) ) ; // You can reuse components const premiumEligible = expr ( and ( isAdult , isVerified ) ) ; 3. Avoid raw() When Possible // Good: Use typed operators const condition = expr ( gte ( 'score' , 80 ) ) ; // Avoid: Raw SQL (SQL injection risk) const condition = expr ( raw ( `score >= ${ userInput } ` ) ) ; 4. Parameterize Dynamic Values // Good: Values are automatically parameterized const minAge = getUserInput ( ) ; const condition = expr ( gte ( 'age' , minAge ) ) ; // Safe: minAge is bound as a parameter, not concatenated Common Patterns Dynamic Filter Builder function buildUserFilter ( options : { minAge ? : number ; tier ? : string ; active ? : boolean ; } ) { const conditions : ExprLike [ ] = [ ] ; if ( options . minAge !== undefined ) { conditions . push ( gte ( 'age' , options . minAge ) ) ; } if ( options . tier ) { conditions . push ( eq ( 'tier' , options . tier ) ) ; } if ( options . active !== undefined ) { conditions . push ( eq ( 'active' , options . active ) ) ; } return conditions . length > 0 ? expr ( and ( ... conditions ) ) : null ; } // Usage const filter = buildUserFilter ( { minAge : 18 , tier : 'premium' } ) ; if ( filter ) { const users = await db . select ( new Table ( 'users' ) ) . where ( filter ) ; } Search with Multiple Criteria function searchProducts ( criteria : { minPrice ? : Decimal ; maxPrice ? : Decimal ; categories ? : string [ ] ; inStock ? : boolean ; } ) { const conditions : ExprLike [ ] = [ ] ; if ( criteria . minPrice ) { conditions . push ( gte ( 'price' , criteria . minPrice ) ) ; } if ( criteria . maxPrice ) { conditions . push ( lte ( 'price' , criteria . maxPrice ) ) ; } if ( criteria . categories ?. length ) { conditions . push ( containsAny ( 'categories' , criteria . categories ) ) ; } if ( criteria . inStock !== undefined ) { conditions . push ( eq ( 'in_stock' , criteria . inStock ) ) ; } return expr ( and ( ... conditions ) ) ; } See Also surql - Template tag for queries