Schémas et Entités

Discret utilise un language de schémas pour décrire les données que vous pouvez insérer.

Syntaxe

Commençons par un exemple simple:

{
    Person {
        name: String,
        nickname: String nullable,
        parents:[Person]
    }
}

Nous avons défini une entité nommée Person qui contient trois champs:

Les noms d'entité sont sensibles à la casse, Person et person définissent deux entités différentes.

Les noms de champs sont sensibles à la casse, un champ nommé name est différent de Name

Champ Scalaires

Discret definit les types scalaires suivant pour stocker vos données:

Les types scalaires sont insensibles à la casse. Par exemple, integer ou iNteGer sont valides.

Par défaut les champs de type scalaires ne peuvent pas être vide (nullable). Mais il est possible de:

il n'est pas possible de combiner nullable and default pour le même champ.

{   
    //avec des valeurs par défaut
    ScalarsDefault {
        name: String default "someone",
        age: Integer default 0,
        height: Float default 3.2,
        is_nice: Boolean default true,
        Is_Nice: boolean default True, //true est insensibles à la casse
        profile: Json default "{}",                
        thumbnail: Base64 default ""
    }

    //avec des valeurs pouvant être vides
    ScalarsNullable {
        name: String nullablE,
        age: Integer NULLABLE, //nullable est insensibles à la casse
        height: Float nullable,
        is_nice: Boolean nullable,
        profile: Json nullable,                 
        thumbnail: Base64 Nullable
    }
}

Champs Relationels

Les champs relationels lient des entités entre elles, permettant de définir des modèles de données complexes. Il y a deux types de champs relationels:

Les champs relationels peuvent être vides, et on ne peut pas leur définir une valeur par défaut.

La syntaxe est la suivante:

{
    Person {
        name: String,
        pet: Pet,           //relation unique
        parents:[Person]    //relation mutiple
    }

    Pet {
        name: String,
    }
}

Un tuple définit par Person ne peut avoir qu'un seul Pet, mais autant parents que vous le souhaitez.

Espace de nom

Les applications complexes peuvent avoir besoin d'un grand nombre d'entités. Il est possible de séparer ces entités dans des espaces de nom afin d'améliorer la modularité de l'application. Vous devriez envisager d'utiliser cette fonctionnalité pour les gros projets.

mod_one {
    Person {
        name : String ,
        surname : String,
        child : [mod_one.Person] ,
        pets: [mod_one.Pet]
    }

    Pet {
        name : String,
    }
}
{
    Person {
        surname : String ,
        parents : [Person] ,
        pets: [mod_one.Pet]
    }
}

Cet exemple possède deux espaces de noms: mod_one, et l'espace de nom par défaut. On peut noter que:

Champs Système

Chaque entité possède un ensemble de champs système dédié au bon fonctionnement de la librarie. Every entity have a set of system fields. Those fields can be queried like regular fields, but only room_id and _binary can be modified directly.

Ces champs peuvent être intérrogés comme les champs que vous avez defini. Mais seul room_id et _binary peuvent être modifiés directement.

Indexes

Le système définit un ensemble d'index qui devraient être suffisant pour garantir de bonnes performances dans la majeure partie des cas d'utilisation.

Si une entité possède un très grand nombre de tuples et que des problèmes de performance se font sentir, il est possible de créer des index personalisés. Cette fonctionalité doit être utilisée avec prudence, car les indexes augmentente la taille des données et ralentissent les insertions.

Les Indexes ne peuvent être utilisés que sur des champs scalaires et systèmes.

Cet exemple crée un index sur le tuple (name, id):

{
    Person {
        name: String,
        nickname: String nullable,
        parents:[Person],
        index(name, id),
    }
}

Désactiver l'indexation plein texte

Par défaut, tout les champs de type String sont indexés ensemble pour fournir une fonctionnalité de recherche de texte libre. Cette fonctionnalité peut être désactivée en utilisant le mot clé no_full_text_index.

Les indexes définit dans l'entité ne sont pas désactivés.

my_data {
    Person(no_full_text_index) {
        name : String,
        index(name), //non désactivé
    }
}

Mettre à jour le modèle

Pendant la durée de vie d'un logiciel, le modèle de données est appelé à évoluer. Un ensemble de règles doivent être respecter pour s'assurer que les évolution ne provoque pas de régressions.

Un changement de modèle de donné doit contenir le modèle complet, pas seulement les modifications. Discret va comparer l'ancien et le nouveau modèle pour s'assurer que les règles suivantes sont respectées:

L'insertion et la modification de champs doit obéir aux règles suivantes.

Cet ensemble de contrainte empêche les regression et permet d'éviter d'avoir à gérer différentes versions du modèle de données.

Prenons un exemple, et considérons la définition suivante comme l'ancien modèle de données.

{
    Person {
        name : String nullable,
        surname: String nullable,
    }
}

Cette mise à jour sera acceptée:

{
    Person {
        //modifié pour accepter les valeurs null
        name : String nullable, 

        //modifié pour interdire les valeur vides, en ajoutant une valeur par defaut        
        surname : String default "john",
        
        //nouveau champ à la fin de l'entité
        parents : [Person],
    }

    //nouvelle entité à la fin de l'espace de nom
    Pet {
        name: String
    }
}
//nouvel espace de nom inséré a la fin
my_data {

}

Mais celle-ci sera rejetée

//erreur:: le nouvel espace de nom est inséré avant l'existant
my_data {

}
{
    //Erreur: nouvelle entité insérée avant l'existant
    Pet {
        name: String
    }

    Person {
        //Erreur: let champ 'name' est supprimé 

        //Erreur: nouveau champ inséré avant l'existant
        parents : [Person],

        //Erreur: champ modifié pour ne plus accepter de valeur vides,
        //mais sans ajouter de valeur par défaut.
        surname : String,
        
    }
}

Dépréciation

Nous avons vu dans le précédent chapitre qu'il est interdit de supprimer des champs et des entités. Il est néanmoins possible d'indiquer aux développeurs de l'application que des champs ou entités ne doivent plus être utilisés en les "dépréciant" avec le mot clé @deprecated.

C'est un mot clé de documentation, les champs et entités dépréciés peuvent toujours être utilisé et aucune erreur ou avertissement ne sera généré.

la syntaxe et la suivante:

{
    @deprecated Person {
        name : String ,
    }

    Pet {
        name : String,
        @deprecated  age : Float NULLABLE,
        weight : Integer NULLABLE,
        is_vaccinated: Boolean NULLABLE,
        INDEX(weight),
    }
}

Dans cet exemple, l'entité Person et le champ Pet.age sont indiqués comme déprécié.