RQL - Raven Query Language



The query pipeline

The query pipeline in RavenDB includes the following main stages:

  1. Detect query source (from)

    • Based on your query, RavenDB will determine the appropriate data source from which to retrieve results.

    • Note: all queries in RavenDB use an index to provide results, even when you don't specify one.

    • The following options are available:

      • from index - Explicitly specify which index to use.

      • from collection - Specify the collection to query.
        RavenDB will decide which index will be used depending on the query criteria.

    • Learn more about these query scenarios in this Query Overview.

  2. Filter the data (where)

    • The index is scanned for records that match the query predicate.
  3. Include related documents (include)

    • Related documents that are included in the query will be retrieved and returned to the client
      along with the resulting matching documents, reducing the need to do another network round trip
      to the database when accessing the included documents.
  4. Sort results (order by)

    • Query results can be sorted.
      For example, you can order by a field value, by the resulting documents' score, by random ordering, etc.
  5. Limit results (limit)

    • You can specify the number of results you want to get back from the query
      and the number of results you want to skip.
  6. Project results (select)

    • Projections are specified when you need to retrieve only specific document fields, instead of the whole full document. This reduces the amount of data sent over the network and is useful when only partial data is needed. When projections are Not defined on the query - then the full document content is retrieved from the document storage.

    • Projections are applied as the last stage after the query has been processed, filtered, sorted, and paged.
      This means that the projection doesn't apply to all the documents in the database,
      only to the results that are actually returned.

    • Data can be loaded (load) from related documents to be used in the projected fields.

    • For each record, the server extracts the requested field:
      If a field is stored in the index - the server will fetch it from the index.
      If a field is Not stored in the index - the server will fetch it from the document storage.

  7. Return results to the client.

RQL keywords and methods

The following keywords and methods are available in RQL:

With the following operators:

  • >=
  • <=
  • <> or !=
  • <
  • >
  • = or ==
  • BETWEEN
  • IN
  • ALL IN
  • OR
  • AND
  • NOT
  • (
  • )

And the following values:

  • true
  • false
  • null
  • string e.g. 'John' or "John"
  • number (long and double) e.g. 17
  • parameter e.g. $param1

declare

You can use the declare keyword to create a JavaScript function that can then be called from a select clause when using a projection. JavaScript functions add flexibility to your queries as they can be used to manipulate and format retrieved results.

// Declare a JavaScript function 
declare function output(employee) {
    // Format the value that will be returned in the projected field 'FullName'
    var formatName = function(x){ return x.FirstName + " " + x.LastName; };
    return { FullName : formatName(employee) };
}

// Query with projection calling the 'output' JavaScript function
from Employees as employee select output(employee)

Values are returned from a declared Javascript function as a set of values rather than in a nested array to ease the projection of retrieved values. See an example for this usage here.

from

The keyword from is used to determine the source data that will be used when the query is executed.
The following options are available:


  • Query a specific collection:    from <collection-name>

// Full collection query 
// Data source: The raw collection documents (Auto-index is Not created)
from "Employees"

// Collection query - by ID 
// Data source: The raw collection documents (Auto-index is Not created)
from "Employees" where id() = "employees/1-A"

// Dynamic query - with filtering
// Data source: Auto-index (server uses an existing auto-index or creates a new one)
from "Employees" where FirstName = "Laura"

  • Query all documents:    from @all_docs

// All collections query
// Data source: All raw collections (Auto-index is Not created)
from @all_docs

// Dynamic query - with filtering 
// Data source: Auto-index (server uses an existing auto-index or creates a new one)
from @all_docs where FirstName = "Laura"

  • Query an index:    from index <index-name>

// Index query
// Data source: The specified index
from index "Employees/ByFirstName"

// Index query - with filtering
// Data source: The specified index
from index "Employees/ByFirstName" where FirstName = "Laura"

where

Use the where keyword with various operators to filter chosen documents from the final result-set.


Operator:    >=, <=, <>, !=, <, >, =, ==

These basic operators can be used with all value types, including 'numbers' and 'strings'.
For example, you can return every document from the Companies collection whose field value = a given input.

from "Companies"
where Name = "The Big Cheese" // Can use either '=' or'=='

Filtering on nested properties is also supported.
So in order to return all companies from 'Albuquerque' we need to execute following query:

from "Companies"
where Address.City = "Albuquerque"

Operator:    between

The operator between returns results inclusively, and the type of border values used must match.
It works on both 'numbers' and 'strings' and can be substituted with the >= and <= operators.

from "Products" 
where PricePerUnit between 10.5 and 13.0 // Using between

from "Products" 
where PricePerUnit >= 10.5 and PricePerUnit <= 13.0 // Using >= and <=

Operator:    in

The operator in is validating if a given field contains passed values.
It will return results if a given field matches any of the passed values.

from Companies 
where Name in ('The Big Cheese', 'Unknown company name')

from Orders 
where Lines[].ProductName in ('Chang', 'Spegesild', 'Unknown product name')

Operator:    all in

This operator checks if all passes values are matching a given field.
Due to its mechanics, it is only useful when used on array fields.

The following query will yield no results in contrast to the in operator.

from "Orders" 
where Lines[].ProductName all in ("Chang", "Spegesild", "Unknown product name")

Removing 'Unknown product name' will return only orders that contain products with both
'Chang' and 'Spegesild' names.

from "Orders"
where Lines[].ProductName all in ("Chang", "Spegesild")

Binary Operators:    AND, OR, NOT

Binary operators can be used to build more complex statements.
The NOT operator can only be used with one of the other binary operators creating OR NOT or AND NOT ones.

from "Companies"
where Name = "The Big Cheese" OR Name = "Richter Supermarkt"

from "Orders"
where Freight > 500 AND ShippedAt > '1998-01-01'

from "Orders"
where Freight > 500 AND ShippedAt > '1998-01-01' AND NOT Freight = 830.75

Subclauses:    (, )

Subclauses can be used along with binary operators to build even more complex logical statements.

group by

The keyword group by is used to create an aggregation query.
Learn more in dynamic group by queries.

include

The keyword include has been introduced to support:

order by

Use order by to perform sorting.
Learn more in this sorting article.

select

Use select to have the query return a projection instead of the full document.
Learn more in this projection article.

load

Use loadwhen you need to use data from a related document in projection.
See an example in this projection article.

limit

Use limit to limit the number of results returned by the query.
Specify the number of items to skip from the beginning of the result set and the number of items to take (return).
This is useful when paging results.

// Available syntax options:
// =========================

from "Products" limit 5, 10       // skip 5, take 10

from "Products" limit 10 offset 5 // skip 5, take 10

from "Products" offset 5          // skip 5, take all the rest

update

To patch documents on the server-side, use update with the desired JavaScript that will be applied to any document matching the query criteria.
For more information, please refer to this patching article.

with

The keyword with is used to determine the data source of a graph query.
There are two types of with clauses, regular with and with edges.

  • with:    with {from Orders} as o
    The above statement means that the data source referred to by the alias o is the result of the from Orders query.

  • with edges:    with edges (Lines) { where Discount >= 0.25 select Product } as cheap
    The above statement means that our data source is the property Lines of the source documents and we filter all lines that match Discount >= 0.25 query.
    The destination referred to by the cheap alias is the product pointed by the Product property of the order line.

match

The keyword match is used to determine the pattern of a graph query.

match (Orders as o)-[Lines as cheap where Discount >= 0.25 select Product]->(Products as p)
The above statement means that we are searching for a pattern that starts with an order and traverse using the order lines referred to by the Lines property where their Discount property is larger than 25% and the destination is the product referred to by the Product property.

A match may contain an edge in both direction, a right edge would look like so (node1)-[right]->(node2)
and a left one would look like so (node1)<-[left]-(node2).

Any combination of edges is allowed in a match clause e.g.
(node1)-[right]->(node2)<-[left]-(node3)

The above match will actually be translated to:
(node1)-[right]->(node2)
and
(node3)-[left]->(node2)
where the and is a set intersection between the two patterns.

RQL comments

Single-line comments:

  • Single-line comments start with // and end at the end of that line.

// This is a single-line comment.
from "Companies"
where Name = "The Big Cheese" OR Name = "Richter Supermarkt"

from "Companies"
where Name = "The Big Cheese" // OR Name = "Richter Supermarkt"

Multiline comments:

  • Multiline comments start with /* and end with */.

/*
This is a multiline comment.
Any text here will be ignored.
*/
from "Companies"
where Name = "The Big Cheese" OR Name = "Richter Supermarkt"

from "Companies"
where Name = "The Big Cheese" /* this part is a comment */ OR Name = "Richter Supermarkt"