Filtering

The WHERE condition is shared among many SQL commands. A condition results in a boolean; and a compound condition, consisting of multiple conditions that are combined with logical operators, is resolved from left to right.

Syntax

[<item>] <operator> <item>

Items

And item can be:

What Description Example

field

Document field

WHERE price > 1000000

field<indexes>

Document field part. To know more about field part look at the full syntax: Document-API-Property

WHERE tags[name='Hi'] OR tags[0...3] IN ('Hello') AND employees IS NOT NULL

record attribute

Record attribute name with @ as prefix

WHERE @type = 'Profile'

Functions

Any Function between the defined ones

WHERE distance(x, y, 52.20, 0.14) <= 30

$variable

Context variable prefixed with $

WHERE $depth <= 3

Record attributes

Name Description Example

@this

returns the record itself

SELECT @this.toJSON() FROM Account

@rid

returns the RID in the form bucket:position. It is null for embedded records. NOTE: using @rid in a "Where" condition slows down queries. Much better to use the RID as target. Example: change SELECT FROM Profile WHERE @rid = #10:44 to SELECT FROM #10:44

@rid = #11:0

@size

returns the record size in bytes

@size > 1024

@type

returns the record type between: 'document', 'column', 'flat', 'bytes'

@type = 'flat'

@out

on an edge, returns the vertex the edge leaves, as a link: @out.name reads a property of that vertex. Plain out is not a field of an edge: it reads as null, and so does out.name, without an error. outV() gives the same vertex

@out = #12:0

@in

on an edge, returns the vertex the edge points to, as a link. Plain in is not a field of an edge either and reads as null. inV() gives the same vertex

@in.name = 'Rome'

Operators

Conditional Operators

Apply to Operator Description Example

any

= or ==

Equals. A list on the right side is compared as a whole, so name = ['a','b'] matches nothing, with or without an index; use IN to match any of several values (since v26.10.2; before, an index expanded the list like IN). Two lists, or two maps, are equal when they hold the same elements in the same order (the same keys for a map) and the numbers in them compare as two numbers do, so tags = [1, 2] also matches a list written with 64-bit integers by the Java API or a client (since v26.11.1; before, the elements were compared by Java class and [1, 2] differed from the same list of long values). Every other element is compared as = compares two scalars, so two values = reports equal are equal as elements too: a java.util.Date, an Instant, a Calendar or a java.sql.Timestamp is equal to the stored LocalDateTime of the same instant inside a list or a map, as it is on its own (since v26.11.1; before, the list was a different value and <> answered its row). <>, IN and CONTAINS follow the same rule. A list indexed BY ITEM holds one entry per element, so it is not used for tags = [1, 2]: the records are scanned. A set, an array or any other collection is compared under the same element rule as a list: two sets whatever their order, any other pair in the order they iterate (since v26.11.1; before, only a java.util.List was, so a Set holding a Date differed from the stored list of the same instant)

name = 'Luke'

any

<=>

Null-safe-equals, is also true if left and right operands are NULL

name <=> word

string

LIKE

Similar to equals, but allows the wildcards ‘%’ that means "any characters", none included ('' LIKE '%' is true, since v26.10.2), and ‘?’ that means "any single character". Use \% and \? to match the characters themselves. LIKE is case sensitive. A pattern with a literal start ('Luk%') uses an ordered index on the property, except a case insensitive one; a pattern starting with a wildcard does not.

name LIKE 'Luk%'

string

ILIKE

Similar to LIKE, but ILIKE is case insensitive.

name ILIKE 'lUk%'

string

NOT LIKE

Negation of LIKE, equivalent to NOT (x LIKE y)

name NOT LIKE 'Leia'

string

NOT ILIKE

Negation of ILIKE, equivalent to NOT (x ILIKE y)

name NOT ILIKE 'lEIA'

any

<

Less than

age < 40

any

<=

Less or equal to

age <= 40

any

>

Greater than

age > 40

any

>=

Greater or equal to

age >= 40

any

<> or !=

Not equal to

age <> 40

any

BETWEEN

The value is between a range. It’s equivalent to <field> >= <from-value> AND <field> <= <to-value>

price BETWEEN 10 AND 30

any

IS

Used to test if a value is NULL

children IS NULL

any

IS NOT

Used to test if a value is not NULL

children IS NOT NULL

record, string (as type name)

INSTANCEOF

Used to check if the record extends a type

@this INSTANCEOF 'Customer' OR @type INSTANCEOF 'Provider'

collection

IN

contains any of the elements listed. Uses the index on the property, including the leading columns of a composite index (transactionId IN (...) on an index over (transactionId, date)), with every list form: IN (a, b), IN [a, b] and a bound parameter. The listed values are looked up in index order, so an ORDER BY on the indexed columns needs no extra sort step. The searched value is converted to the type of the listed items when needed, so ? IN doubleList with the String '7' finds 7.0 with or without an index, like CONTAINS. A property on the left side is never converted: stringProp IN [7.0] does not match '7', exactly like stringProp = 7.0 and the index. Without an index, IN (?) with a single parameter and IN (SELECT ...) compare numbers and dates by value too, so a Long 7 matches an Integer 7, and 1.50 matches 1.5 (since v26.10.1)

name IN ['European','Asiatic']

collection

NOT IN

contains all of the elements not listed. Does not use index: an index can look up the listed values, not their complement, so the type is scanned. If the type is large, add a second indexed condition to the query to drive the lookup

name NOT IN ['European','Asiatic']

collection

CONTAINS

true if the collection contains at least one element that satisfy the next condition. Use @this as right item for lists. Condition can be a single item: in this case the behaviour is like the IN operator. A one-element list on the right, CONTAINS [x], compares x under the = rule, so a BINARY value matches by content and an Integer matches a stored Long (since v26.11.1)

children CONTAINS (name = 'Luke') ; map.values() CONTAINS (name = 'Luke') ; ['a','b'] CONTAINS (@this ILIKE 'A')

collection

CONTAINSALL

true if every element of the right collection is contained in the left collection. A single value on the left is treated as a one-element collection (since v26.10.1; before, it was always false). CONTAINSALL (<condition>) is true when every element satisfies any condition, e.g. items CONTAINSALL (name IS NOT NULL) (any condition since v26.10.1; before, only OR conditions). On a list indexed BY ITEM the index looks up one of the elements and every record it returns is checked for the others, so a right side of several elements uses the index too, and answers as a scan does whether it is a list, a set or an array parameter such as int[] (since v26.11.1; before, several elements were scanned, and an array of several elements answered like CONTAINSANY). An empty right side is true for every collection and is answered by a scan. A BINARY (byte[]) right side is one value searched for, as CONTAINS and CONTAINSANY read it (since v26.11.1; before, it was expanded into its bytes)

children.name CONTAINSALL ['Luke','Leia']

collection

CONTAINSANY

true if at least one element of the right collection is contained in the left collection. A single value on the left is treated as a one-element collection, so uuid CONTAINSANY ['u1','u2'] answers like uuid IN ['u1','u2'] (since v26.10.1; before, it was always false). CONTAINSANY (<condition>) is true when at least one element satisfies the condition, so it is false on an empty collection (since v26.10.1; before, it behaved like CONTAINSALL)

children.name CONTAINSANY ['Jacen','Jaina','Ben']

map

CONTAINSKEY

true if the map contains at least one key equals to the requested. You can also use map.keys() CONTAINS in place of it

connections CONTAINSKEY 'Luke'

map

CONTAINSVALUE

true if the map contains at least one value equals to the requested. You can also use map.values() CONTAINS in place of it

connections CONTAINSVALUE 10:3

string

CONTAINSTEXT

When used against an indexed field, a lookup in the index will be performed with the text specified as key. When there is no index a simple Java indexOf will be performed. So the result set could be different if you have an index or not on that field

text CONTAINSTEXT 'jay'

string

MATCHES

Matches the string using a Regular Expression. Use the modifier (?s) to make . match also newlines, and (?i) for case insensitive patterns.

text MATCHES `\b[A-Z0-9.%+-@[A-Z0-9.-]\.[A-Z]{2,4}\b]`

LIKE, ILIKE, MATCHES are not using full-text indexes.
A full-text index matches words, not whole values, so it only answers CONTAINSTEXT and the full-text search functions. Exact operators (=, IN, CONTAINS, CONTAINSANY, CONTAINSALL) never use it and always return exact matches, also on a list indexed BY ITEM. To have an exact lookup indexed, create a regular (UNIQUE/NOTUNIQUE) index. (Since v26.10.1: before, name = 'x' on a full-text indexed property also returned every record sharing a word with 'x'.)
CONTAINS asks whether the collection on the left holds a single value: either one matching the condition, or, when the right side is a plain value, one equal to it. Put a collection on the right and it is searched for as one element, so tags CONTAINS ['red','blue'] matches a row whose tags holds the nested list ['red','blue'], and not a row whose tags is ['red','green','blue']. To compare two collections, use CONTAINSALL (every element of the right is present on the left) or CONTAINSANY (at least one is). This applies equally when the right side is produced by an expression such as 'red blue'.split(' '), and with a list indexed BY ITEM, which is used only for a single value or a right side of exactly one element (since v26.11.1; before, the index answered tags CONTAINS ['red','blue'] like CONTAINSANY).

Logical Operators

Operator Description Example

AND

true if both the conditions are true

name = 'Luke' AND surname LIKE 'Sky%'

OR

true if at least one of the condition is true

name = 'Luke' OR surname LIKE 'Sky%'

NOT

true if the condition is false. NOT needs parenthesis on the right with the condition to negate

NOT (name = 'Luke')

NULL and unknown

Comparing with a missing or NULL value is neither true nor false but unknown, as in standard SQL. This applies to =, <>, !=, <, <=, >, >=, BETWEEN, LIKE, ILIKE and MATCHES (LIKE, ILIKE and MATCHES since v26.11.1). A WHERE keeps a record only when the condition is true, and NOT of an unknown stays unknown, so WHERE age <> 5 and WHERE NOT (age = 5) do not return records without age, the same as age NOT IN [5]. Likewise age = NULL and age <> NULL match nothing, and a boolean used as a value (SELECT age <> 5, CASE WHEN age <> 5 ...) is NULL for those records.

To test for a missing value use IS NULL, IS NOT NULL or the null-safe <=>. To keep the records without a value, write it out: WHERE age <> 5 OR age IS NULL.

IN follows the same logic: 3 NOT IN [4, NULL] is unknown, because the NULL might be 3, so a NOT IN whose list or sub-query holds a NULL returns no record. Use NOT IN (SELECT k FROM U WHERE k IS NOT NULL) to leave the NULL out (since v26.11.1 for a sub-query; before, a NULL row of the sub-query was ignored).

Arithmetic with a NULL operand is NULL, so WHERE age - 4 < 6 does not return records without age either (see Math Operators).

Mathematics Operators

Apply to Operator Description Example

Numbers

+

Plus

age + 34

Numbers

-

Minus

salary - 34

Numbers

*

Multiply

factor * 1.3

Numbers

/

Divide

total / 12

Numbers

%

Mod

total % 3

Methods

Also called "Field Operators", are SQL-Methods.

Variables

ArcadeDB supports variables managed in the context of the command/query. By default, some variables are created. Below the table with the available variables:

Name Description Command(s)

$parent

Get the parent context from a sub-query. Example: SELECT FROM V LET $type = (TRAVERSE out() FROM $parent.$current.children)

SELECT and TRAVERSE

$current

Current record to use in sub-queries to refer from the parent’s variable

SELECT and TRAVERSE

$depth

The current depth of nesting

TRAVERSE

$path

The string representation of the current path. Example: #6:0.in.#5:0#.out. You can also display it with SELECT $path FROM (TRAVERSE out() FROM V)

TRAVERSE

$stack

The List of operation in the stack. Use it to access to the history of the traversal

TRAVERSE

$history

The set of all the records traversed as a Set<RID>

TRAVERSE

To set custom variable use the LET keyword.

Wildcards

Symbol Description Example

%

Matches all strings that contain an unknown substring of any length at the position of %

"%DB" "A%DB" "Arcade%" all match "ArcadeDB"

?

Matches all strings that contain an unknown character at the position of ?

"N?SQL" matches "NoSQL" but not "NewSQL"

Filtering for strings containing wildcards characters can be done by escaping with backslash, i.e. \%, \?.