Firestore en mode Datastore (Datastore) est compatible avec divers types de données pour les valeurs de propriété, parmi lesquels :
- Entiers
- Nombres à virgule flottante
- Chaînes
- Dates
- Données binaires
Pour obtenir la liste complète des types, consultez la section Propriétés et types de valeurs.
Propriétés et types de valeurs
Les valeurs de données associées à une entité consistent en une ou plusieurs propriétés. Chaque propriété a un nom, et une ou plusieurs valeurs. Une propriété peut avoir des valeurs de plus d'un type, et deux entités peuvent avoir des valeurs de types différents pour la même propriété. Les propriétés peuvent être indexées ou non indexées (les requêtes qui ordonnent ou filtrent une propriété P ignorent les entités pour lesquelles P n'est pas indexée.) Une entité peut avoir 20 000 propriétés indexées au maximum.
Les types de valeurs suivants sont acceptés :
Lorsqu'une requête implique une propriété avec des valeurs de types mixtes, Datastore utilise un ordre déterministe basé sur les représentations internes :
- Valeurs Null
- Nombres à virgule fixe
- Entiers
- Dates et heures
- Valeurs booléennes
- Séquences d'octets
- Chaîne Unicode
- Clés Blobstore
- Nombres à virgule flottante
- Clés Datastore
Étant donné que les chaînes de texte et d'octets longues ne sont pas indexées, aucun tri n'est défini pour celles-ci.
Types de propriétés
NDB est compatible avec les types de propriétés suivants :
Type de propriété | Description |
---|---|
IntegerProperty | Entier signé de 64 bits |
FloatProperty | Nombre à virgule flottante avec deux décimales |
BooleanProperty | Valeur booléenne |
StringProperty | Chaîne Unicode, jusqu'à 1 500 octets, indexée |
TextProperty | Chaîne Unicode, longueur illimitée, non indexée |
BlobProperty | Chaîne d'octets non interprétée : Si vous définissez indexed=True : jusqu'à 1 500 octets, indexée ;Si indexed est False (valeur par défaut) : longueur illimitée, non indexée.Argument de mot clé facultatif : compressed .
|
DateTimeProperty
| Date et heure (voir Propriétés de date et d'heure) |
DateProperty
| Date (voir Propriétés de date et d'heure) |
TimeProperty
| Heure (voir Propriétés de date et d'heure) |
GeoPtProperty
| Emplacement géographique. Il s'agit d'un objet ndb.GeoPt
doté des attributs lat et lon . Tous deux sont des nombres à virgule flottante.
Vous pouvez construire un objet avec deux nombres à virgule flottante, par exemple ndb.GeoPt(52.37, 4.88) , ou avec une chaîne ndb.GeoPt("52.37, 4.88")
(il s'agit en fait de la même classe que
db.GeoPt ).
|
KeyProperty | Clé Datastore Argument de mot clé facultatif : kind=kind, pour exiger que les clés attribuées à cette propriété aient toujours le genre indiqué. Il peut s'agir d'une chaîne ou d'une sous-classe Model. |
BlobKeyProperty
| Clé Blobstore Correspond à BlobReferenceProperty dans l'ancienne API DB, mais sa valeur est un élément BlobKey au lieu d'un élément BlobInfo . Vous pouvez construire un élément BlobInfo à partir de cette valeur à l'aide de BlobInfo(blobkey) . |
UserProperty | Objet utilisateur |
StructuredProperty
| Inclut un genre de modèle dans un autre, par valeur (voir Propriétés structurées). |
LocalStructuredProperty
| Semblable à StructuredProperty , mais la représentation sur disque est un blob opaque et n'est pas indexée (voir Propriétés structurées).Argument de mot clé facultatif : compressed .
|
JsonProperty
| La valeur est un objet Python (comme une liste, un dictionnaire ou une chaîne) sérialisable à l'aide du module json de Python. Datastore stocke la sérialisation JSON sous forme de blob. Non indexée par défaut.Argument de mot clé facultatif : compressed .
|
PickleProperty
| La valeur est un objet Python (comme une liste, un dictionnaire ou une chaîne) sérialisable à l'aide du protocole de pickle de Python. Datastore stocke la sérialisation avec pickle sous forme de blob. Non indexée par défaut. Argument de mot clé facultatif : compressed .
|
GenericProperty | Valeur générique Utilisée principalement par la classe Expando , mais également utilisable de manière explicite. Elle peut être de type int , long , float , bool , str , unicode , datetime , Key , BlobKey , GeoPt , User ou None .
|
ComputedProperty
| Valeur calculée à partir d'autres propriétés par une fonction définie par l'utilisateur (voir Propriétés calculées). |
Certaines de ces propriétés possèdent un argument de mot clé facultatif, compressed
. Si la propriété est définie sur compressed=True
, ses données sont compressées avec gzip sur le disque.
Cela prend moins d'espace, mais l'encodage et le décodage lors des opérations d'écriture et de lecture nécessitent l'utilisation du processeur.
La compression et la décompression sont "paresseuses". Une valeur de propriété compressée ne sera décompressée que la première fois que vous y accédez. Si vous lisez une entité contenant une valeur de propriété compressée et que vous la réécrivez sans accéder à la propriété compressée, elle ne sera ni décompressée, ni compressée. Le cache en contexte participe également à ce schéma paresseux, mais Memcache stocke toujours la valeur compressée pour les propriétés compressées.
En raison du temps CPU supplémentaire nécessaire à la compression, il est généralement préférable de n'utiliser des propriétés compressées que si les données sont trop volumineuses sans elles. N'oubliez pas que la compression basée sur gzip est en général inefficace pour les images et autres données multimédias, car ces formats sont déjà compressés à l'aide d'un algorithme de compression qui leur est propre (par exemple, JPEG pour les images).
Options des propriétés
La plupart des types de propriétés acceptent des arguments standards. Le premier d'entre eux est un argument positionnel facultatif spécifiant le nom Datastore de la propriété. Il permet d'attribuer à la propriété un nom différent dans Datastore de celui utilisé du côté de l'application. Cela permet généralement de réduire l'espace dans Datastore et à celui-ci d'utiliser des noms de propriété abrégés même si, dans votre code, les noms sont plus longs et plus significatifs. Par exemple,
Cela est particulièrement utile dans le cas des propriétés répétées pour lesquelles vous attendez un grand nombre de valeurs par entité.
De plus, la plupart des types de propriétés acceptent les arguments de mots clés suivants :
Argument | Type | Par défaut | Description |
---|---|---|---|
indexed | bool | En général, True | Permet d'inclure la propriété dans les index Datastore. S'il est défini sur False , les valeurs ne peuvent pas être interrogées, mais les écritures sont plus rapides. Les types de propriétés ne sont pas tous compatibles avec l'indexation. La définition de indexed sur True échoue pour ceux-ci.Les propriétés non indexées entraînent moins d'opérations en écriture que les propriétés indexées. |
repeated | bool | False | La valeur de propriété est une liste Python contenant les valeurs du type sous-jacent (voir Propriétés répétées). Ne peut pas être combiné avec required=True ou default=True .
|
required | bool | False | Une valeur doit être spécifiée pour la propriété. |
default | Type sous-jacent de la propriété | None | Valeur par défaut de la propriété si aucune n'est explicitement spécifiée. |
choices | Liste de valeurs du type sous-jacent | None | Liste facultative des valeurs autorisées. |
validator | Fonction | None | Fonction facultative permettant de valider et éventuellement de convertir la valeur. Sera appelé avec des arguments (prop, value) et doit renvoyer la valeur (éventuellement convertie) ou générer une exception. Le fait d'appeler à nouveau la fonction sur une valeur convertie ne devrait pas modifier davantage la valeur.
Par exemple, le renvoi de |
verbose_name | chaîne | None
| Libellé HTML facultatif à utiliser dans les frameworks de formulaire Web tels que jinja2. |
Propriétés répétées
Toute propriété pour laquelle repeated=True
est défini devient une propriété répétée.
La propriété prend une liste de valeurs du type sous-jacent plutôt qu'une seule valeur.
Par exemple, la valeur d'une propriété définie avec IntegerProperty(repeated=True)
est une liste d'entiers.
Datastore peut voir plusieurs valeurs pour ce type de propriétés. Un enregistrement d'index distinct est créé pour chaque valeur, ce qui a une incidence sur la sémantique des requêtes. Pour obtenir un exemple, consultez la section Interroger des propriétés répétées.
Cet exemple utilise une propriété répétée :
...
Cela crée une entité Datastore contenant les éléments suivants :
Lors de l'interrogation de la propriété tags
, cette entité satisfera à une requête pour 'python'
ou 'ruby'
.
Lors de la mise à jour d'une propriété répétée, vous pouvez lui attribuer une nouvelle liste ou modifier la liste existante.
En cas d'attribution d'une nouvelle liste, les types de ses éléments sont immédiatement validés. Les types d'éléments non valides (par exemple, l'attribution de [1, 2]
à art.tags
ci-dessus) génèrent une exception.
En cas de modification de la liste, le changement apporté n'est pas immédiatement validé.
Au lieu de cela, la valeur est validée lorsque vous écrivez l'entité dans Datastore.
Datastore conserve l'ordre des éléments de la liste dans une propriété répétée. Vous pouvez ainsi attribuer un sens à leur classement.
Propriétés de date et d'heure
Trois types de propriétés permettent de stocker les valeurs liées à la date et à l'heure :
DateProperty
TimeProperty
DateTimeProperty
Ces propriétés prennent des valeurs appartenant aux classes correspondantes (date
, time
et datetime
) du module datetime
Python standard.
Le type le plus général des trois est DateTimeProperty
, qui désigne à la fois une date du calendrier et une heure de la journée. Les autres sont parfois utiles dans des cas spéciaux, où seule une date (comme une date de naissance) ou une heure (par exemple, une heure de réunion) est nécessaire.
Pour des raisons techniques, DateProperty
et TimeProperty
sont des sous-classes de DateTimeProperty
, mais vous ne devez pas compter sur cette relation d'héritage (notez qu'elle diffère des relations d'héritage existant entre les classes sous-jacentes définies par le module datetime
lui-même).
Remarque : Les temps d'horloge App Engine sont toujours exprimés en temps universel coordonné (UTC). C'est important si vous utilisez la date ou l'heure actuelle (datetime.datetime.now()
) en tant que valeur, ou si vous effectuez une conversion entre des objets "datetime" et des horodatages POSIX ou des tuples de temps.
Toutefois, aucune information de fuseau horaire explicite n'est stockée dans Datastore. Par conséquent, en faisant preuve de prudence, vous pouvez vous en servir pour représenter les heures locales dans n'importe quel fuseau horaire, si vous utilisez l'heure actuelle ou les conversions.
Chacune de ces propriétés comporte deux options de mots clés booléens supplémentaires :
Option | Description |
---|---|
auto_now_add
| Définit la propriété sur la date et l'heure actuelles lors de la création de l'entité. Vous pouvez remplacer cette propriété manuellement. Lorsque l'entité est mise à jour, la propriété ne change pas. Pour ce comportement, utilisez auto_now .
|
auto_now
| Définit la propriété sur la date et l'heure actuelles lors de la création de l'entité et à chaque mise à jour. |
Ces options ne peuvent pas être combinées avec repeated=True
.
Dans les deux cas, la valeur par défaut est False
. Si toutes deux sont définies sur True
, auto_now
est prioritaire.
Il est possible de remplacer la valeur d'une propriété présentant l'option auto_now_add=True
, mais pas celle d'une propriété présentant l'option auto_now=True
.
La valeur automatique n'est générée que lorsque l'entité est écrite, ce qui signifie que ces options ne fournissent pas de valeurs par défaut de manière dynamique.
Ces détails diffèrent de l'ancienne API DB.
Remarque : Lorsqu'une transaction écrivant une propriété qui présente l'option auto_now_add=True
échoue et fait l'objet d'une nouvelle tentative, elle réutilise la même valeur de temps que lors de la tentative d'origine plutôt que de la mettre à jour vers l'heure de la nouvelle tentative. Si la transaction échoue de manière permanente, la valeur de la propriété est toujours définie dans la copie en mémoire de l'entité.
Propriétés structurées
Vous pouvez structurer les propriétés d'un modèle.
Par exemple, vous pouvez définir une classe de modèle Contact contenant une liste d'adresses, chacune avec une structure interne.
Les propriétés structurées (type StructuredProperty
) vous permettent d'effectuer cette opération. Exemple :
...
...
Cela crée une seule entité Datastore dotée des propriétés suivantes :
La relecture d'une telle entité reconstruit exactement l'entité Contact
d'origine.
Bien que les instances Address
soient définies à l'aide de la même syntaxe que celle employée pour les classes de modèle, ce ne sont pas de véritables entités.
Elles ne possèdent pas leurs propres clés dans Datastore.
Elles ne peuvent pas être récupérées indépendamment de l'entité Contact
à laquelle elles appartiennent.
Toutefois, une application peut interroger les valeurs de leurs champs individuels. Consultez la section Filtrer par valeur de propriété structurée.
Notez que Datastore considère address.type
, address.street
et address.city
comme des tableaux parallèles, mais que la bibliothèque NDB masque cet aspect et construit la liste correspondante d'instances Address
.
Vous pouvez spécifier les options de propriété habituelles pour les propriétés structurées (sauf indexed
). Le nom Datastore est le deuxième argument positionnel dans ce cas (le premier étant la classe de modèle utilisée pour définir la sous-structure).
Lorsque vous n'avez pas besoin d'interroger les propriétés internes d'une sous-structure, vous pouvez utiliser une propriété structurée locale (LocalStructuredProperty
). Si vous remplacez StructuredProperty
par LocalStructuredProperty
dans l'exemple ci-dessus, le comportement du code Python est identique, mais Datastore ne voit qu'un blob opaque pour chaque adresse. L'entité guido
créée dans l'exemple serait stockée comme suit :
name = 'Guido'
address = <blob opaque pour {'type': 'home', 'city': 'Amsterdam'}>
address = <blob opaque pour {'type': 'work', 'city': 'SF', 'street': 'Spear St'}>
L'entité sera relue correctement. Comme les propriétés de ce type sont toujours non indexées, vous ne pouvez pas interroger les valeurs d'adresse.
Remarque : Une propriété StructuredProperty
dotée d'une propriété imbriquée (qu'elle soit structurée ou non) n'accepte qu'une seule couche de propriétés répétées. La propriété StructuredProperty
peut être répétée ou la propriété imbriquée peut être répétée, mais pas les deux. Pour contourner le problème, vous pouvez utiliser LocalStructuredProperty
, qui ne présente pas cette contrainte (mais n'autorise pas les requêtes sur ses valeurs de propriété).
Propriétés calculées
Les propriétés calculées (ComputedProperty
) sont des propriétés en lecture seule dont la valeur est calculée à partir d'autres valeurs de propriété par une fonction fournie par l'application. Notez qu'une propriété calculée n'est compatible qu'avec les types acceptés par les propriétés génériques. La valeur calculée est écrite dans Datastore de sorte qu'elle puisse être interrogée et affichée dans la visionneuse Datastore, mais la valeur stockée est ignorée lorsque l'entité est relue à partir de Datastore. À la place, la valeur est recalculée en appelant la fonction chaque fois que la valeur est demandée. Exemple :
...
Cela stocke une entité avec les valeurs de propriété suivantes :
Si nous changeons le nom en "Nickie" et demandons la valeur de name_lower
, "nickie" est renvoyé :
Remarque : Utilisez ComputedProperty
si l'application interroge la valeur calculée. Si vous souhaitez simplement utiliser la version dérivée dans le code Python, définissez une méthode standard ou utilisez la propriété @property
intégrée de Python.
Remarque : Si vous créez un modèle sans clé spécifiée manuellement et que vous comptez plutôt sur Datastore pour générer automatiquement l'ID de l'entité, alors une propriété put()
ne pourra pas lire le champ d'ID la première fois que vous effectuez une opération ComputedProperty
puisque celui-ci est calculé avant que l'ID ne soit généré.
Si vous avez besoin d'une propriété ComputedProperty
qui utilise l'ID de l'entité, vous pouvez utiliser la méthode allocate_ids
pour générer un ID et une clé avec lesquels créer l'entité, afin que votre propriété ComputedProperty
soit en mesure de référencer cet ID sur la première méthode "put()" de l'entité.
Propriétés de messages Google Protocol RPC
La bibliothèque Google Protocol RPC utilise des objets
Message
pour les données structurées. Ils peuvent représenter des requêtes RPC, des réponses ou d'autres éléments. NDB fournit une API permettant de stocker les objets Message
de Google Protocol RPC en tant que propriétés d'entités.
Supposons que vous définissiez une sous-classe Message
:
...
Vous pouvez stocker des objets Note
dans Datastore en tant que valeurs de propriété d'entité à l'aide de l'API msgprop
de NDB.
...
...
Si vous souhaitez interroger des noms de champs, ceux-ci doivent être indexés.
Vous pouvez spécifier une liste de noms de champs qui seront indexés avec le paramètre indexed_fields
sur MessageProperty
.
MessageProperty
accepte de nombreuses options de propriété, mais pas toutes. Les options compatibles sont les suivantes :
name
repeated
required
default
choices
validator
verbose_name
Les propriétés de messages ne sont pas compatibles avec l'option de propriété indexed
. Vous ne pouvez pas indexer les valeurs Message
. Vous pouvez toutefois indexer les champs d'un message comme décrit ci-dessus.
Les messages imbriqués (à l'aide de MessageField
) fonctionnent également :
...
MessageProperty
possède une option de propriété spéciale, protocol
, qui spécifie la façon dont l'objet Message est sérialisé vers Datastore. Les valeurs sont les noms de protocoles utilisés par la classe protorpc.remote.Protocols
. Les noms de protocoles acceptés sont protobuf
et protojson
; la valeur par défaut est protobuf
.
msgprop
définit également EnumProperty
, un type de propriété pouvant servir à stocker une valeur protorpc.messages.Enum
. Exemple :
...
...
EnumProperty
stocke la valeur sous forme d'entier. En fait, EnumProperty
est une sous-classe de IntegerProperty
.
Par conséquent, vous pouvez renommer vos valeurs d'énumération sans avoir à modifier les entités déjà stockées, mais vous ne pouvez pas les renuméroter.
EnumProperty accepte les options de propriétés suivantes :
name
indexed
repeated
required
default
choices
validator
verbose_name
À propos des modèles d'entité NDB
Un modèle d'entité NDB peut définir des propriétés. Les propriétés d'entité sont un peu comme les membres de données des classes Python, une manière structurée de stocker des données. Elles sont aussi un peu comme les champs d'un schéma de base de données.
Pour définir un modèle de données, une application type définit une classe qui hérite de Model
avec certains attributs de classe de propriété.
Par exemple,
...
Ici, username
, userid
et email
sont des propriétés de Account
.
Il existe plusieurs autres types de propriétés. Certains sont pratiques pour représenter les dates et les heures, et disposent de fonctionnalités pratiques de mise à jour automatique.
Une application peut ajuster le comportement d'une propriété en spécifiant des options sur la propriété. Celles-ci peuvent faciliter la validation, définir des valeurs par défaut ou modifier l'indexation des requêtes.
Un modèle peut comporter des propriétés plus complexes. Les propriétés répétées ressemblent à des listes. Les propriétés structurées sont semblables à des objets. Les propriétés calculées en lecture seule sont définies via des fonctions, ce qui facilite la définition d'une propriété en fonction d'une ou de plusieurs autres propriétés. Les modèles Expando peuvent définir des propriétés de manière dynamique.