evitaDB - Fast e-commerce database
logo
page-background

Schema API design

The article contains basic concepts around evitaDB entity schemas and an example of how to define them from Java code.

All schema classes are designed as immutable and follow similar rules as entities - including naming conventions and versioning. They don't follow the soft-removal approach, though. The changes in the schema affect the database structure and once applied, the previous schema of the catalog is no longer available.

Evolution

evitaDB is designed to be schema-full with automatic evolution support. One can start without a schema and immediately create new entities in the collection without reasoning about the structure. evitaDB works in "auto evolution" mode and builds schemas along the way. The existing schemas are still validated on each entity insertion/update - you will not be allowed to store same attribute the first time as a number type and next time as a string. First usage will set up the attribute schema, which will have to be respected from that moment on.

Default schema implicitly creates all attributes as nullable, filterable and non-array data types as sortable. This means the client is immediately able to filter / sort almost by anything, but the database itself will consume a lot of resources.

evitaDB can operate in strict schema mode when the structure is defined up-front, and then sealed so that all entities must strictly correspond to the predefined schema and violations will generate exceptions. This behaviour needs to be specified at the moment of collection of the creation.

There are several partial lax modes between the strict and the lax mode - see EvolutionMode.java

Schema definition example

A schema can be programmatically defined this way:

Java
1evita.updateCatalog(2	"testCatalog",3	session -> {4		session.defineEntitySchema(PRODUCT)5			/* all is strictly verified but associated data and references can be added on the fly */6			.verifySchemaButAllow(EvolutionMode.ADDING_ASSOCIATED_DATA, EvolutionMode.ADDING_REFERENCES)7			/* product are not organized in the tree */8			.withoutHierarchy()9			/* prices are referencing another entity stored in Evita */10			.withPrice()11			/* en + cs localized attributes and associated data are allowed only */12			.withLocale(Locale.ENGLISH, new Locale("cs", "CZ"))13			/* here we define list of attributes with indexes for search / sort */14			.withAttribute("code", String.class, whichIs -> whichIs.unique())15			.withAttribute("url", String.class, whichIs -> whichIs.unique().localized())16			.withAttribute("oldEntityUrls", String[].class, whichIs -> whichIs.filterable().localized())17			.withAttribute("name", String.class, whichIs -> whichIs.filterable().sortable())18			.withAttribute("ean", String.class, whichIs -> whichIs.filterable())19			.withAttribute("priority", Long.class, whichIs -> whichIs.sortable())20			.withAttribute("validity", DateTimeRange.class, whichIs -> whichIs.filterable())21			.withAttribute("quantity", BigDecimal.class, whichIs -> whichIs.filterable().indexDecimalPlaces(2))22			.withAttribute("alias", Boolean.class, whichIs -> whichIs.filterable())23			/* here we define set of associated data, that can be stored along with entity */24			.withAssociatedData("referencedFiles", ReferencedFileSet.class)25			.withAssociatedData("labels", Labels.class, whichIs -> whichIs.localized())26			/* here we define references that relate to another entities stored in Evita */27			.withReferenceToEntity(28				CATEGORY,29				CATEGORY,30				Cardinality.ZERO_OR_MORE,31				whichIs ->32					/* we can specify special attributes on relation */33					whichIs.filterable().withAttribute("categoryPriority", Long.class, thatIs -> thatIs.sortable())34			)35			/* for faceted references we can compute "counts" */36			.withReferenceToEntity(37				BRAND,38				BRAND,39				Cardinality.ZERO_OR_ONE,40				whichIs -> whichIs.faceted())41			/* references may be also represented be entities unknown to Evita */42			.withReferenceTo(43				"stock",44				"stock",45				Cardinality.ZERO_OR_MORE,46				whichIs -> whichIs.faceted()47			)48			/* finally apply schema changes */49			.updateVia(session);50	}51);52

Author: Ing. Jan Novotný

Date updated: 15.12.2022

Documentation Source