Skip to content

Latest commit

 

History

History
111 lines (95 loc) · 5.98 KB

File metadata and controls

111 lines (95 loc) · 5.98 KB
title perex date author proofreading
Query API design
The article introduces the basics of querying EvitaDB using its query API, including constructing queries, making requests, and handling responses, with Java code examples.
15.12.2022
Ing. Jan Novotný
done

The evitaQL (evitaDB Query Language) entry point is represented by Query.java, and it looks like a Lisp flavoured language. It always starts with the name of the function, followed by a set of arguments in brackets. You can even use other functions in these arguments.

evitaQL is represented by a simple String that is parsed to an abstract syntax tree, which consists of constraints (Constraint.java encapsulated in Query.java We design the evitaQL String representation to look similar to a query defined in the Java notation.

Developers should create their queries in their code by using the static query methods in Query.java and then composing internal constraints from the static methods in QueryConstraints.java. When this class is statically imported, the Java query definition looks like the string form of the query.

Conversion of evitaQL from String to AST and back

There is also QueryParser.java which allows for parsing the query from the String. The string notation can be created anytime by calling the toString() method on the Query.java object.

The parser supports passing values by reference copying the proven approach from a JDBC prepared statement allowing the use of the character ? in the query and providing an array of correctly sorted input parameters. It also supports the so-called named queries, which are widely used in the Spring framework, using variables in the query with the :name format and providing a Map with the named input parameters.

In the opposite direction, it offers the toStringWithParameterExtraction method on the Query.java object which allows for the creating of the string format for evitaQL in the form of a prepared statement and extracting all parameters in separate array.

Defining queries in Java code

This is an example how the query is composed and evitaDB requested. The example statically imports two classes: Query.java and QueryConstraints.java

final EvitaResponse<SealedEntity> entities = evita.queryCatalog(
	"testCatalog",
	session -> {
		return session.query(
			query(
				collection(Entities.BRAND),
				filterBy(
					and(
						primaryKey(1, 2, 3),
						language(Locale.ENGLISH)
					)
				),
				orderBy(
					asc("name")
				),
				require(
					entityBody(), attributes(), associatedData(), allPrices(), references()
				)
			),
			SealedEntity.class
		);
	}
);

The query can also contain "dirty" parts - i.e. null constraints and unnecessary parts:

final EvitaResponse<SealedEntity> entities = evita.queryCatalog(
	"testCatalog",
	session -> {
		return session.query(
			query(
				collection(Entities.BRAND),
				filterBy(
					and(
						primaryKey(1, 2, 3),
						locale != null ? language(Locale.ENGLISH) : null
					)
				),
				orderBy(
					asc("name")
				),
				require(
					entityBody(), attributes(), associatedData(), allPrices(), references()
				)
			),
			SealedEntity.class
		);
	}
);

The query is automatically cleaned and unnecessary constraints are purged before being processed by the evitaDB engine.

There are several handy visitors (more will be added) that allow you to work with the query. They are placed in the package visitor, and some have quick methods in the QueryUtils.java class.

The query can be "pretty-printed" by using the prettyPrint method on the Query.java class.