
Schema API design
The article contains basic concepts around evitaDB entity schemas and an example of how to define them from Java code.
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.
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.
Schema definition example
A schema can be programmatically defined this way:
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