Firestore en modo Datastore (Datastore) admite una variedad de tipos de datos para valores de propiedad. Se incluyen, entre otros:
- Números enteros
- números de punto flotante
- Strings
- Fechas
- Datos binarios
Para obtener una lista completa de los tipos, consulta Tipos de valores y propiedades.
Tipos de valores y propiedades
Los valores de datos asociados con una entidad constan de una o más propiedades. Cada propiedad tiene un nombre y uno o más valores. Una propiedad puede tener valores de más de un tipo, y dos entidades pueden tener valores de diferentes tipos para la misma propiedad. Las propiedades pueden o no estar indexadas (las consultas que ordenan o filtran en una propiedad P ignorarán las entidades en las que P no esté indexada). Una entidad puede tener como máximo 20,000 propiedades indexadas.
Se admiten los tipos de valor siguientes:
Cuando una consulta incluye una propiedad con valores de varios tipos, Datastore usa un orden determinista basado en las representaciones internas:
- Valores nulos
- Números de coma fija
- Números enteros
- fechas y horarios
- Valores booleanos
- Secuencias de bytes
- String de Unicode
- Claves de Blobstore
- números de coma flotante
- Claves de Datastore
Las strings de texto largas y las strings de bytes largas no están indexadas y no tienen un orden definido.
Tipos de propiedad
NDB es compatible con las funciones siguientes:
Tipo de propiedad | Descripción |
---|---|
IntegerProperty | Número entero de 64 bits con firma. |
FloatProperty | Número de punto flotante de doble precisión |
BooleanProperty | Booleano |
StringProperty | String de Unicode; hasta 1,500 bytes, indexada |
TextProperty | Strings de Unicode; longitud ilimitada, no indexada |
BlobProperty | String de bytes sin interpretar: si estableces indexed=True , hasta 1500 bytes, indexado;i indexed es False (el valor predeterminado), longitud ilimitada sin indexar.Argumento de palabra clave opcional: compressed .
|
DateTimeProperty
| Fecha y hora (consulta Propiedades de fecha y hora) |
DateProperty
| Fecha (consulta Propiedades de fecha y hora) |
TimeProperty
| Hora (consulta Propiedades de fecha y hora) |
GeoPtProperty
| Ubicación geográfica. Esta es un objeto ndb.GeoPt .
El objeto tiene atributos lat y lon , ambos son números de punto flotante.
Puedes construir uno con dos números de punto flotante como ndb.GeoPt(52.37, 4.88) o con una string ndb.GeoPt("52.37, 4.88") .
Esta es en realidad la misma clase que
db.GeoPt .
|
KeyProperty | Clave de Datastore Argumento de palabra clave opcional: tipo=kind, para requerir que las claves asignadas a esta propiedad siempre tengan el tipo indicado. Puede ser una string o una subclase Model. |
BlobKeyProperty
| Clave de Blobstore Corresponde a BlobReferenceProperty en la API de base de datos anterior, pero el valor de la propiedad es BlobKey en lugar de BlobInfo ; puedes construir un BlobInfo con estos a través de BlobInfo(blobkey) . |
UserProperty | Objeto de usuario. |
StructuredProperty
| Incluye un tipo de modelo dentro de otro, según el valor (consulta Propiedades estructuradas) |
LocalStructuredProperty
| Al igual que StructuredProperty , pero la representación en el disco es un BLOB opaco y no está indexado (consulta Propiedades estructuradas).Argumento de palabra clave opcional: compressed .
|
JsonProperty
| El valor es un objeto de Python (como una lista, un diccionario o una string) que se puede serializar con el módulo de Python json . Datastore almacena la serialización de JSON como un blob. Sin indexar de forma predeterminada.Argumento de palabra clave opcional: compressed .
|
PickleProperty
| El valor es un objeto de Python (como una lista, un diccionario o una string) que se puede serializar con el protocolo de serialización de Python. Datastore almacena la serialización como un blob. Sin indexar de forma predeterminada. Argumento de palabra clave opcional: compressed .
|
GenericProperty | Valor genérico En su mayor parte, lo usa la clase Expando , pero también se puede usar de manera explícita. Su tipo puede ser cualquiera de estos: int , long , float , bool , str , unicode , datetime , Key , BlobKey , GeoPt , User o None .
|
ComputedProperty
| Valor computado de otras propiedades a partir de una función definida por el usuario. (Consulta Propiedades computadas). |
Algunas de estas propiedades tienen un argumento de palabra clave opcional, compressed
. Si la propiedad tiene compressed=True
, entonces sus datos se comprimen con gzip en el disco.
Ocupa menos espacio, pero necesita CPU para codificarse o decodificarse en las operaciones de escritura y lectura.
Tanto la compresión como la descompresión son "lentas"; un valor de propiedad comprimido solo se descomprimirá la primera vez que accedas a él. Si lees una entidad que contiene un valor de propiedad comprimida y lo escribes sin acceder a esa propiedad, no se descomprimirá ni comprimirá en absoluto. La memoria almacenada en caché en contexto también participa en este esquema lento, pero Memcache siempre almacena el valor comprimido para propiedades contraídas.
Debido al tiempo adicional que la CPU necesita para la compresión, generalmente es mejor usar propiedades comprimidas solo si los datos fueran demasiado grandes para ajustarse sin ellos. Recuerda que la compresión basada en gzip generalmente no es efectiva para imágenes y otros datos de medios, porque esos formatos ya están comprimidos con un algoritmo de compresión específico de medios (p. ej., JPEG para imágenes).
Opciones de propiedad
La mayoría de los tipos de propiedades admiten algunos argumentos estándares. El primero es un argumento de posicionamiento opcional que especifica el nombre de la propiedad de Datastore. Puedes utilizar esta opción para darle a la propiedad un nombre diferente en Datastore que en el punto de vista de la aplicación. Un uso común es reducir el espacio en Datastore para que use nombres de propiedad abreviados, mientras que tu código usa nombres más largos y significativos. Por ejemplo:
Esto es muy útil para propiedades repetidas en las que esperas muchos valores por entidad.
Además, la mayoría de los tipos de propiedad admiten los argumentos de palabras clave siguientes:
Argumento | Tipo | Predeterminado | Descripción |
---|---|---|---|
indexed | bool | Generalmente True . | Incluye la propiedad en los índices de Datastore; si es False , los valores no se pueden consultar, pero las escrituras son más rápidas. No todos los tipos de propiedad admiten la indexación; configurar indexed como True falla en estos casos.Las propiedades no indexadas cuestan menos operaciones de escritura que las propiedades indexadas. |
repeated | bool | False | El valor de propiedad es una lista de Python que contiene valores del tipo subyacente (consulta Propiedades repetidas). No se puede combinar con required=True ni default=True .
|
required | bool | False | La propiedad debe tener un valor especificado. |
default | Tipo subyacente de la propiedad | Ninguno | Valor predeterminado de la propiedad si no se especifica explícitamente. |
choices | Lista de valores de tipo subyacente | None | Lista opcional de valores permitidos. |
validator | Función | None | Función opcional para validar y posiblemente forzar el valor. Se llamará con argumentos (prop, value) y debe mostrar el valor (posiblemente forzado) o generar una excepción. Volver a llamar a la función en un valor forzado no debería modificar más el valor.
(Por ejemplo, está bien que se muestre |
verbose_name | string | None
| Etiqueta HTML opcional para usar en formularios web de marcos de trabajo, como jinja2. |
Propiedades repetidas
Cualquier propiedad con repeated=True
se convierte en una propiedad repetida.
La propiedad toma una lista de valores del tipo subyacente, en lugar de un solo valor.
Por ejemplo, el valor de una propiedad definida con IntegerProperty(repeated=True)
es una lista de número enteros.
Datastore puede ver varios valores de esa propiedad. Se crea un registro de índice separado para cada valor. Esto afecta la semántica de consulta; consulta Consultar propiedades repetidas para ver un ejemplo.
Este ejemplo usa una propiedad repetida:
...
Esto crea una entidad de Datastore con el siguiente contenido:
Cuando se consulta la propiedad tags
, esta entidad satisfará una consulta para 'python'
o 'ruby'
.
Cuando se actualiza una propiedad repetida, puedes asignarle una lista nueva o mutar la lista existente allí.
Cuando asignas una lista nueva, los tipos de los elementos de lista se validan inmediatamente. Los tipos de elementos no válidos (por ejemplo, la asignación de [1, 2]
a art.tags
anterior) muestran una excepción.
Cuando mutas la lista, el cambio no se valida inmediatamente.
En su lugar, el valor se validará cuando escribas la entidad en Datastore.
Datastore conserva el orden de los elementos de lista en una propiedad repetida, por lo que puede asignar algún significado a su orden.
Propiedades de fecha y hora
Hay tres tipos de propiedades disponibles para almacenar valores relacionados con la fecha y la hora:
DateProperty
TimeProperty
DateTimeProperty
Estos toman valores pertenecientes a las clases correspondientes (date
, time
, datetime
) del módulo estándar de Python datetime
.
El más general de los tres es DateTimeProperty
, que denota tanto una fecha del calendario como una hora del día; los otros son ocasionalmente útiles para fines especiales que son obligatorios en una fecha (como una fecha de nacimiento) o en una hora (como una hora de reunión).
Por razones técnicas, DateProperty
y TimeProperty
son subclases de DateTimeProperty
, pero no debes depender de esta relación de herencia (y ten en cuenta que difiere de las relaciones de herencia entre las clases subyacentes definidas por el mismo módulo datetime
).
Nota: Los tiempos de reloj de App Engine siempre se expresan en tiempo universal coordinado (UTC). Esto es relevante si usas la fecha o la hora actuales (datetime.datetime.now()
) como un valor o una conversión entre objetos datetime y marcas de tiempo POSIX o tuplas de tiempo.
Sin embargo, no se almacena información explícita de la zona horaria en Datastore, por lo que, si tienes cuidado, puedes usarlos para representar las horas locales en cualquier zona horaria, si usas la hora actual o las conversiones.
Cada una de estas propiedades tiene dos opciones de palabras clave booleanas adicionales:
Opción | Descripción |
---|---|
auto_now_add
| Establece la propiedad en la fecha/hora actual cuando se crea la entidad. Puedes anular manualmente esta propiedad. Cuando la entidad se actualiza, la propiedad no cambia. Para ese comportamiento, usa auto_now .
|
auto_now
| Establece la propiedad en la fecha/hora actual cuando se crea la entidad y cada vez que se actualiza. |
Estas opciones no se pueden combinar con repeated=True
.
Ambos se configuran como el valor predeterminado False
. Si ambos están configurados como True
, auto_now
tiene prioridad.
Es posible anular el valor de una propiedad con auto_now_add=True
, pero no de una con auto_now=True
.
El valor automático no se genera hasta que se escribe la entidad; es decir, estas opciones no proporcionan valores predeterminados dinámicos.
(Estos detalles difieren de la API de db anterior).
Nota: Cuando una transacción que escribe una propiedad con auto_now_add=True
falla y se vuelve a intentar, volverá a usar el mismo valor de tiempo que en el intento original, en lugar de actualizarlo hasta el momento del reintento. Si la transacción falla de forma permanente, el valor de la propiedad se seguirá estableciendo en la copia en memoria de la entidad.
Propiedades estructuradas
Puedes estructurar las propiedades de un modelo.
Por ejemplo, puedes definir una clase de modelo Contact que contenga una lista de direcciones, cada una con estructura interna.
Las propiedades estructuradas (de tipo StructuredProperty
) te permiten hacer eso, como se muestra a continuación:
...
...
Esto crea una entidad única de Datastore con las siguientes propiedades:
Si se vuelve a leer, esa entidad reconstruye exactamente la entidad de Contact
original.
Aunque las instancias de Address
se definen con la misma sintaxis que las clases de modelo, no son entidades completas.
No tienen sus propias claves en Datastore.
No se pueden recuperar independientemente de la entidad de Contact
a la que pertenecen.
Sin embargo, una aplicación puede consultar los valores de sus campos individuales; consulta Filtra por valores de propiedad estructurada.
Ten en cuenta que address.type
, address.street
y address.city
se leen como arreglos paralelos desde el punto de vista de Datastore, pero la biblioteca de NDB oculta este aspecto y construye la lista correspondiente de instancias de Address
.
Puedes especificar las opciones de propiedad habituales para las propiedades estructuradas (excepto indexed
). El nombre de Datastore es el segundo argumento de posicionamiento en este caso (el primero es la clase de modelo que se usa para definir la subestructura).
Cuando no necesitas consultar las propiedades internas de una subestructura, puedes usar una propiedad local estructurada (LocalStructuredProperty
) en su lugar. Si reemplazas StructuredProperty
por LocalStructuredProperty
en el ejemplo anterior, el comportamiento del código de Python es el mismo, pero Datastore ve solo un BLOB opaco para cada dirección. La entidad guido
que se crea en el ejemplo, se almacenaría de esta forma:
name = "Guido"
address = <opaque blob for {"type": "home", "city": "Amsterdam"}>
address = <opaque blob for {"type": "work", "city": "SF",
"street": "Spear St"}>
La entidad se leerá con éxito. Como las propiedades de este tipo nunca están indexadas, no puedes consultar los valores de dirección.
Nota: StructuredProperty
con una propiedad anidada (esté o no estructurada) admite solo una capa única de propiedades repetidas. Se puede repetir StructuredProperty
o la propiedad anidada, pero no ambas. Una solución alternativa es usar LocalStructuredProperty
, que no tiene esta restricción (pero no permite realizar consultas sobre los valores de sus propiedades).
Propiedades computadas
Las propiedades calculadas (ComputedProperty
) son propiedades de solo lectura cuyo valor se calcula a partir de otros valores de propiedad mediante una función suministrada por la aplicación. Ten en cuenta que una propiedad calculada solo admite los tipos que son compatibles con propiedades genéricas. El valor calculado se escribe en Datastore para que se pueda consultar y mostrar en el lector de Datastore, pero el valor almacenado se ignora cuando la entidad vuelve a leer desde Datastore; por el contrario, el valor se vuelve a calcular llamando a la función cada vez que se solicita el valor. Por ejemplo:
...
Esto almacena una entidad con los valores de propiedad siguientes:
Si cambiamos el nombre a "Nickie" y pedimos el valor de name_lower
, muestra "nickie":
Nota: Usa ComputedProperty
si la aplicación realiza una consulta para el valor calculado. Si solo deseas usar la versión derivada en el código de Python, define un método normal o usa la función incorporada @property
de Python.
Nota: Si creas un modelo sin una clave especificada de forma manual y, en su lugar, confías en Datastore para generar automáticamente el ID de la entidad, entonces, en tu primer put()
, ComputedProperty
no podrá leer el campo del ID, ya que el campo se calcula antes de que se genere el ID.
Si necesitas una ComputedProperty
que use el ID de la entidad, puedes usar el método allocate_ids
para generar un ID y una clave con los cuales crear la entidad, de modo que tu ComputedProperty
pueda hacer referencia a ese ID en el primer put() de la entidad.
Propiedades del mensaje del protocolo de RPC de Google
La biblioteca del RPC del protocolo de Google usa objetos
Message
para datos estructurados. Pueden representar solicitudes RPC, respuestas y otros elementos. NDB proporciona una API para almacenar objetos Message
del RPC del protocolo de Google como propiedades de la entidad.
Supongamos que defines una subclase Message
:
...
Puedes almacenar objetos Note
en Datastore como valores de propiedad de la entidad mediante la API msgprop
de NDB.
...
...
Si deseas consultar los nombres de los campos, estos deben estar indexados.
Puedes especificar una lista de nombres de campo que se indexarán con el parámetro indexed_fields
para MessageProperty
.
MessageProperty
admite muchas de las opciones de propiedad, pero no todas. Es compatible con:
name
repeated
required
default
choices
validator
verbose_name
Las propiedades de mensaje no admiten la opción de propiedad indexed
. No puedes indexar los valores Message
. (Puedes indexar los campos de un mensaje como se describe anteriormente).
Los mensajes anidados (que usan MessageField
) también funcionan:
...
MessageProperty
tiene una opción de propiedad especial, protocol
, que especifica cómo se serializa el objeto de mensaje en Datastore. Los valores son nombres de protocolo como los usa la clase protorpc.remote.Protocols
. Los nombres de protocolo admitidos son protobuf
y protojson
. El valor predeterminado es protobuf
.
msgprop
también define EnumProperty
, un tipo de propiedad que se puede usar para almacenar un valor protorpc.messages.Enum
en una entidad. Ejemplo:
...
...
EnumProperty
almacena el valor como un número entero. De hecho, EnumProperty
es una subclase de IntegerProperty
.
Esto implica que puedes cambiar el nombre de sus valores de enumeración sin tener que modificar las entidades ya almacenadas, pero no puedes renumerarlos.
EnumProperty admite las opciones de propiedad siguientes:
name
indexed
repeated
required
default
choices
validator
verbose_name
Acerca de los modelos de entidad NDB
Un modelo de entidad NDB puede definir propiedades. Las propiedades de la entidad son un poco como miembros de datos de las clases de Python, una forma estructurada de almacenar datos; también son como campos en un esquema de base de datos.
Una aplicación típica define un modelo de datos definiendo una clase que hereda de Model
con algunos atributos de clase de propiedad.
Por ejemplo:
...
Aquí, username
, userid
y email
son propiedades de Account
.
Hay muchos otros tipos de propiedades. Algunos son útiles para representar fechas y horas, y tienen funciones de actualización automática convenientes.
Una aplicación puede ajustar el comportamiento de una propiedad especificando opciones en la propiedad. Estos pueden facilitar la validación, establecer valores predeterminados o cambiar la indexación de consultas.
Un modelo puede tener propiedades más complejas. Las propiedades repetidas son como listas. Las propiedades estructuradas son como objetos. Las propiedades computadas de solo lectura se definen a través de funciones; esto facilita la definición de una propiedad en términos de una o más propiedades. Los modelos de Expando pueden definir propiedades de manera dinámica.