The terms 'attribute' and 'field', while containing nuances, are sometimes used interchangeably. An attribute is a generic word to describe the different types described below.
A collection defined in JSON Schema for the purpose of document modeling may contain these different types of attributes:
- a root attribute, which in the case of NoSQL is always a document (whereas JSON Schema allows the root to be other types)
- a field
- a pattern field
- a choice
- an array item
- a subschema
- a reference to a previously defined attribute
All the details of how to introduce an attribute in the hierarchical schema view can be found in the page about the manipulation of Attribute boxes in Tree diagram.
There is only one root possible per document. For the purpose of a NoSQL document schema, the root attribute can only be of type: document.
Properties can be filled for the root attribute. They are essentially the properties of the collection.
One or more attributes (child field, pattern field, or choice) can be created, as seen below.
The nominal case is for an attribute to have only one type. The JSON specification however allows a field to be of multiple types. The application UI is able to define and maintain multiple types for a field. If the data types in the multiple set are all scalar types (string, number, boolean, null), then you just press the + sign to the right of the data type property:
As a result, the data type in the ERD appears as "multi":
The Properties Pane displays an array of properties for each of the data types:
To expand the list of properties for a given data type, press the + sign on the left. To suppress a data type, click the X on the right.
If one of the data types is complex (array or object, and also list, map, struct, etc. in other targets), then you must use a choice, cfr below. With v6.2.2, and only for JSON Schema and MongoDB, it is also possible to specify multiple data type with at least one complex data type, using the simpler method already used with scalar data types:
The nature of attributes is different for document, array, or others. Documents are allowed to have one or more Fields, Pattern Fields, and/or Choices as attributes. Arrays are allowed to have one or more Array Items and/or Choices as attributes. As for all other types of fields, the only possible attribute is ‘Choice’.
With version 5.3.0, Hackolade introduced the possibility, in the JSON target only, to have an undefined data type called "any". This allows you to have no restriction on the data type. While the declaration of the "any" data type is explicit in the UI, the result in JSON Schema is the absence of a data type declaration. In other words, the selection of the "any" data type:
results in the following JSON Schema declaration:
Pattern fields (or pattern properties) function in exactly the same way as standard fields, with only one exception: the name (in the name-value pair) is not a fixed string, but a regex pattern. This can be particularly useful in MongoDB in combination with ‘dot notation’. It is also the basis for storage in Firebase and Firestore.
The sub-document key in the key-value pair is not a fixed word, but a variable. These keys are typically controlled by a regular expression pattern, hence the name of 'pattern field'. You should not look at it as a 'field name', but as a key to a sub-document when embedding. It lets you easily access the right sub-document inside an array or main document, using dot notation.
In Hackolade, the above example is modeled this way:
In JSON Schema, there are 4 possible choices: “allOf”, “anyOf”, “oneOf”, and “noneOf”. Each of these attributes contains an array, with each attribute of the array representing content that will be matched against. The choice of “allOf”, “anyOf”, “oneOf”, or “not” determines how the validation processor will treat the results of the matches:
- allOf requires that all attributes in the suschema are matched successfully.
- anyOf requires one or more of the attributes in the subschema to be matched successfully.
- oneOf requires one, and only one, of the attributes in the subschema to match successfully.
- noneOf requires that no attribute in the subschema is matched successfully.
Schema definitions can use “allOf”, “anyOf”, “oneOf”, and “noneOf” individually or in combination, providing significant flexibility for defining attributes that have complex definitions or contextual relationships. These choices apply both to fields and to field properties. In both cases, the only possible attribute of Choice is a Subschema.
if-then-else conditional subschemas
With version 5 of Hackolade, support was introduced for the conditional application of subschemas. The if, then and else keywords allow the application of a subschema based on the outcome of another schema.
A misapplication of this feature introduced with JSON Schema draft-07, is for multiple data types. Multiple data types have been supported by earlier drafts of JSON Schema, whether for scalar/primitive data types, or when combining with complex data types through the use of choices. It is also desirable to do so for backward-compatibility.
A better application of this feature is when having to allow the application of a subschema depending on the outcome of another schema:
- If if is valid, then then must also be valid (and else is ignored)
- If if is invalid, then else must also be valid (and then is ignored)
- If then or else is not defined, if behaves as if they have a value of true
- If then and/or else appear in a schema without if, then then and else are ignored
This is the only possible attribute type of an Array field. Different types of array items are possible for a same parent attribute. Each can have from 0 to n occurences, but can be limited by the minItems and maxItems properties of the Array.
This is the only possible attribute type of a Choice field. The subschema is a document with all the schema possibilities of a JSON object.
Definitions, maintained at 3 distinct levels (collection, model, and external) can be re-used as an attribute. More details here.
Pick from list
Any field previously created in the same collection can be repeated without having to be typed again. Note that they are not linked to each other, so a change in one will not be synched.