1. Descripción general
Esta serie de codelabs (instructivos prácticos y de autoaprendizaje) tiene como objetivo ayudar a los desarrolladores de Google App Engine (estándar) a modernizar sus apps con una serie de migraciones. La mayoría de estas migraciones implican dejar de lado los servicios agrupados del entorno de ejecución original porque los entornos de ejecución de última generación son más flexibles y ofrecen a los usuarios una mayor variedad de opciones de servicios. Otra forma de modernizar una app es actualizarla a un producto más nuevo, y ese es el tema de este codelab.
Los usuarios de App Engine que acceden a Datastore con las bibliotecas cliente de Cloud NDB o Cloud Datastore no necesitan realizar más migraciones. Sin embargo, Cloud Firestore representa el almacén de datos NoSQL más reciente, escalable y altamente disponible con funciones de la base de datos en tiempo real de Firebase.
Estás en el lugar correcto si eres desarrollador y sientes la necesidad de usar Firestore para aprovechar sus funciones o, al menos, tienes suficiente interés en explorar lo que implica la migración. En este instructivo, se explica cómo migrar una aplicación de App Engine que usa Cloud Datastore a Cloud Firestore.
Obtendrás información para hacer las siguientes acciones
- Reconocer las diferencias entre Datastore y Firestore
- Migra de Cloud Datastore a Cloud Firestore
Requisitos
- Un proyecto de Google Cloud Platform con lo siguiente:
- Habilidades básicas de Python
- Conocimiento práctico de los comandos comunes de Linux
- Conocimientos básicos sobre el desarrollo y la implementación de aplicaciones de App Engine
- Se recomienda completar el codelab Módulo 3, incluida su portabilidad a Python 3, antes de comenzar este (Módulo 6).
- Una app de App Engine en el módulo 3 de Cloud Datastore Python 3 en funcionamiento
Encuesta
¿Cómo usarás este codelab?
2. Fondo
El Datastore de App Engine se convirtió en su propio producto en 2013, Google Cloud Datastore, y ahora los desarrolladores pueden acceder a él fuera de App Engine. Al año siguiente, Google adquirió Firebase. En ese momento, se conocía por su base de datos en tiempo real.
En los años siguientes, los equipos de Firebase y Cloud Datastore trabajaron para integrar algunas de las funciones de Firebase en Datastore. Como resultado, en 2017, se lanzó la próxima generación de Cloud Datastore. Para reflejar la herencia de algunas funciones de Firebase, se cambió su nombre a Cloud Firestore.
Cloud Firestore se convirtió en el mecanismo de almacenamiento NoSQL predeterminado para los proyectos de Google Cloud. Las apps nuevas pueden usar Cloud Firestore de forma nativa, mientras que las bases de datos existentes de Datastore se convirtieron a Firestore de forma interna y ahora operan como "Firestore en modo Datastore" para preservar la compatibilidad con las operaciones de Datastore. Como resultado, las aplicaciones solo pueden operar Cloud Firestore en uno de esos modos y, una vez configurado, no se puede cambiar.
Actualmente, cuando los usuarios crean proyectos nuevos y seleccionan una solución de NoSQL, se les solicita que elijan Firestore en modo Datastore o Firestore en modo nativo. Una vez que los usuarios agregan entidades de Datastore, no pueden cambiar a Firestore y, de manera similar, una vez que se selecciona el modo nativo de Firestore, ya no pueden volver a Datastore (o, mejor dicho, a Firestore en modo Datastore). Para obtener más detalles, lee la página sobre cómo elegir entre Cloud Firestore en modo Datastore o el modo nativo de Firestore en la documentación. Para migrar una app a Firestore, se debe crear un proyecto nuevo, exportar Datastore y, luego, importarlo a Firestore. El objetivo de este instructivo es brindarles a los desarrolladores una idea de las diferencias entre el uso de Cloud Datastore y Cloud Firestore.
Esta migración no es una que esperamos que realicen los usuarios, por lo que es opcional. Si bien existen ventajas evidentes de usar Cloud Firestore de forma nativa, como la autenticación de clientes, la integración de reglas de Firebase y, por supuesto, la base de datos en tiempo real de Firebase, los pasos de migración son "inconvenientes":
- Debes usar un proyecto diferente al de tu app actual.
- No se puede cambiar a Firestore en modo nativo un proyecto en el que una app haya agregado entidades de Datastore.
- Del mismo modo, un proyecto que seleccionó Firestore en modo nativo no puede volver a Firestore en modo Datastore.
- No hay ninguna herramienta de migración que pueda transmitir datos de un proyecto a otro.
- Algunas funciones críticas de Datastore, como los espacios de nombres y un mayor rendimiento de escritura (más de 10,000/s), no están disponibles en Firestore.
- Las herramientas de importación y exportación son escenarios "primitivos" y "todo o nada".
- Si tu app tiene muchas entidades de Datastore, puede tardar muchas horas en exportarlas y, luego, importarlas a Firestore.
- Durante este período, tu aplicación o servicio no podrá escribir ni actualizar datos.
- Las actividades de migración se consideran uso normal, por lo que te recomendamos que las distribuyas (en las cuotas diarias, si es posible) para minimizar los costos.
- Debido a que tu nuevo servicio se ejecuta en un proyecto diferente, necesitarás un período para que se propaguen las actualizaciones de DNS.
- Datastore y Firestore tienen modelos de datos similares, pero diferentes, por lo que la migración requiere actualizar el funcionamiento de la app o el servicio.
- Las consultas de ancestros de Datastore ahora son consultas de colección de Firestore (la opción predeterminada).
- Las consultas de tipo amplio de Datastore son consultas de grupo de colecciones de Firestore
- Los índices y el manejo son diferentes, etc.
Dicho esto, si tienes una app bastante sencilla que deseas migrar, te estás preparando para simular una migración o simplemente quieres obtener información sobre Datastore y Firestore, ¡continúa!
Usuarios de Python 2: Este codelab de migración opcional solo se presenta en Python 3. Sin embargo, dado que Cloud Firestore también admite la versión 2.x, los usuarios pueden interpolar las diferencias de uso. Un ejemplo es que los registros de Firestore usan cadenas Unicode (en lugar de cadenas de bytes), por lo que se requiere un indicador inicial u'' para los literales de cadena de Python 2, lo que significa que una función store_visit() de 2.x se verá de la siguiente manera:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection(u'Visit')
doc_ref.add({
u'timestamp': datetime.now(),
u'visitor': u'{}: {}'.format(remote_addr, user_agent),
})
Aparte de eso, la biblioteca cliente debería funcionar de manera similar. El único otro problema que se debe tener en cuenta es que la biblioteca de Cloud Firestore 2.x está "congelada" en lo que respecta al desarrollo, por lo que cada vez más funciones nuevas solo estarán disponibles en la biblioteca cliente de Firestore 3.x.
Si continúas con esta migración, estos son los pasos principales del instructivo:
- Configurar/trabajo previo
- Agrega la biblioteca de Cloud Firestore
- Actualizar archivos de la aplicación
3. Configurar/trabajo previo
Antes de comenzar con la parte principal del instructivo, configuremos nuestro proyecto, obtengamos el código e implementemos la app de modelo de referencia para que comencemos a trabajar con el código.
1. Configura el proyecto
Te recomendamos que vuelvas a usar el mismo proyecto que usaste para completar el codelab del módulo 3. De manera alternativa, puedes crear un proyecto nuevo o reutilizar otro proyecto existente. Asegúrate de que el proyecto tenga una cuenta de facturación activa y que App Engine (app) esté habilitado.
2. Obtén app de ejemplo del modelo de referencia
Uno de los requisitos previos a este codelab es tener una app de ejemplo del módulo 3 que funcione. Si aún no tienes uno, completa el instructivo del módulo 3 (vínculo anterior) antes de avanzar. De lo contrario, si ya estás familiarizado con su contenido, puedes comenzar leyendo el código del Módulo 3 a continuación.
Sin importar si usas el tuyo o el nuestro, el código del módulo 3 es el que tendremos en cuenta. Este codelab del módulo 6 te guiará en cada paso y, cuando se complete, debería parecerse al código en el punto FINALIZAR. (Este instructivo solo está disponible para Python 3).
- INICIO: Repositorio del módulo 3
- FINALIZAR: Repositorio del módulo 6
- Repositorio completo (clonar o descargar el archivo ZIP)
El directorio de archivos del módulo 3 (el tuyo o el nuestro) debería verse así:
$ ls
README.md main.py templates
app.yaml requirements.txt
3. (Vuelve a ) implementar la app del Módulo 3
Los pasos del trabajo previo restantes para ejecutar ahora sin estos:
- Vuelve a familiarizarte con la herramienta de línea de comandos de
gcloud(si es necesario). - (Vuelve a )implementa el código del módulo 3 en App Engine (si es necesario).
Después de ejecutar esos pasos de forma correcta y confirmemos que está funcionando, avanzaremos en este instructivo y comenzaremos con los archivos de configuración.
Requisitos de Python 2
- Asegúrate de que
app.yaml(aún) haga referencia a los paquetes agrupados de terceros:grpcioysetuptools. - Asegúrate de que
appengine_config.pysiga usandopkg_resourcesygoogle.appengine.ext.vendorpara dirigir la app a recursos de terceros. - En la siguiente sección, cuando actualices
requirements.txt, debes usargoogle-cloud-firestore==1.9.0, ya que esa es la versión final de la biblioteca cliente de Python de Firestore compatible con la versión 2.x.- Si tu
requirements.txttiene una entrada paragoogle-cloud-core, déjala como está. - Borra
liby vuelve a instalarlo conpip install -t lib -r requirements.txt.
- Si tu
4. Actualiza los archivos de configuración (agrega la biblioteca de Cloud Firestore)
Además de la configuración, los próximos pasos necesarios son actualizar la configuración y, luego, los archivos de la aplicación. En el primer caso, el único cambio de configuración es un intercambio de paquetes menor en tu archivo requirements.txt, así que hagámoslo ahora.
Reemplaza la línea google-cloud-datastore por google-cloud-firestore en requirements.txt para que se vea de la siguiente manera:
Flask==1.1.2
google-cloud-firestore==2.0.2
Recomendamos usar las versiones más recientes de cada biblioteca. Los números de las versiones anteriores son los más recientes en el momento en que se redactó este documento. El código en la carpeta del repositorio FINISH se actualiza con más frecuencia y puede tener una versión más reciente.
No hay otros cambios de configuración, por lo que app.yaml y templates/index.html permanecen como están.
5. Actualizar archivos de la aplicación
Solo hay un archivo de aplicación, main.py, por lo que todos los cambios de esta sección afectan solo a ese archivo.
1. Importaciones
Cambiar la importación del paquete es un cambio menor de datastore a firestore:
- ANTES:
from google.cloud import datastore
- DESPUÉS:
from google.cloud import firestore
2. Acceso a Firestore
Después de inicializar Flask, crea tu cliente de Firestore. Realiza un cambio similar al anterior, pero para la inicialización del cliente:
- ANTES:
app = Flask(__name__)
ds_client = datastore.Client()
- DESPUÉS:
app = Flask(__name__)
fs_client = firestore.Client()
Si realizaste la migración de Cloud NDB a Cloud Datastore, ya hiciste el trabajo más pesado para llegar a Cloud Firestore. Con Datastore, creas registros de datos en forma de entidades compuestas por propiedades comunes y las agrupas por claves. Los registros de datos en Firestore son documentos, que se componen de pares clave-valor y se agrupan en colecciones. Migrar desde Datastore requiere que pienses en estas diferencias, ya que se materializarán cuando crees registros de datos y cuando los consultes. Los resultados pueden variar según la complejidad del código de Datastore.
En Datastore, realizas consultas basadas en el tipo de entidad junto con criterios de filtrado y ordenamiento. En el caso de Firestore, la consulta de datos es similar. Veamos un ejemplo rápido, suponiendo estos valores de búsqueda, clientes (ds_client o fs_client, respectivamente) e importaciones:
from datetime import datetime
from firestore.Query import DESCENDING
OCT1 = datetime(2020, 10, 1)
LIMIT = 10
En el caso de Datastore, consultemos las diez entidades Visit más recientes posteriores al 1 de octubre de 2020 en orden descendente:
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)
Hacer lo mismo para Firestore, desde la colección Visit:
query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()
La consulta de la app de ejemplo es más simple (no tiene cláusula "WHERE"). A modo de repaso, aquí se muestra el código de Cloud Datastore:
- ANTES:
def store_visit(remote_addr, user_agent):
entity = datastore.Entity(key=ds_client.key('Visit'))
entity.update({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
ds_client.put(entity)
def fetch_visits(limit):
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
return query.fetch(limit=limit)
Cuando migres a Firestore, verás que la creación de documentos nuevos es similar a la de entidades, y las consultas son como se mostraron anteriormente.
- DESPUÉS:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection('Visit')
doc_ref.add({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
def fetch_visits(limit):
visits_ref = fs_client.collection('Visit')
visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
direction=firestore.Query.DESCENDING).limit(limit).stream())
return visits
La función principal root() sigue siendo la misma, al igual que el archivo de plantilla index.html. Verifica los cambios, guárdalos, impleméntalos y revísalos.
6. Resumen/Limpieza
Implemente la aplicación
Vuelve a implementar la app con gcloud app deploy y confirma que funciona. El código ahora debería coincidir con el contenido del repositorio del módulo 6 (o una versión 2.x si esa era tu preferencia).
Si alcanzaste esta serie sin hacer ninguno de los Codelabs anteriores, la aplicación en sí no cambia. Registra todas las visitas a la página web principal (/) y tendrá esta apariencia una vez que hayas visitado el sitio muchas veces:

Felicitaciones por completar esta migración opcional del módulo 6. Es probable que esta sea una de las últimas migraciones que puedes realizar en lo que respecta al almacenamiento de datos de App Engine. Una alternativa de migración que puedes considerar es alojar tu app en un contenedor para Cloud Run si aún no lo hiciste (consulta los módulos 4 y 5, y los codelabs vinculados a continuación).
Opcional: Limpieza
¿Qué te parece limpiar a fin de evitar que se te facture hasta que estés listo para pasar a la siguiente codelab de migración? Como desarrolladores existentes, es probable que ya estés al día en la información sobre precios de App Engine.
Opcional: Inhabilita la app
Si aún no estás listo para continuar con el siguiente instructivo, inhabilita tu app a fin de evitar que se apliquen cargos. Cuando estés listo para pasar al siguiente codelab, puedes volver a habilitarla. Aunque tu app esté inhabilitada, no recibirá tráfico que genere cargos. Sin embargo, si se excede la cuota gratuita, se te cobrará por el uso de Firestore. así que borra lo suficiente para que quede dentro de ese límite.
Por otro lado, si no vas a continuar con las migraciones y quieres borrar todo por completo, puedes cerrar tu proyecto.
Próximos pasos
Además de este instructivo, puedes considerar otros codelabs sobre módulos de migración:
- Módulo 7: Listas de tareas en cola de envío de App Engine (obligatorio si usas las listas de tareas en cola [enviar])
- Agrega tareas de envío
taskqueuede App Engine a la app del módulo 1 - Prepara a los usuarios para la migración a Cloud Tasks en el módulo 8
- Agrega tareas de envío
- Módulo 4: Migra a Cloud Run con Docker
- Organiza tu aplicación en contenedores para que se ejecute en Cloud Run con Docker
- Esta migración te permite permanecer en Python 2.
- Módulo 5: Migra a Cloud Run con Cloud Buildpacks
- Crea contenedores para tu app a fin de que se ejecute en Cloud Run con paquetes de Cloud Build
- No necesitas conocer los detalles de Docker, contenedores, ni
Dockerfile. - Requiere que tu app ya se haya migrado a Python 3 (Buildpacks no es compatible con Python 2).
7. Recursos adicionales
Problemas o comentarios de los Codelabs del módulo de migración de App Engine
Si encuentras algún problema con este Codelab, primero busca el problema antes de enviarlo. Vínculos para buscar y crear problemas nuevos:
Recursos de migración
En la siguiente tabla, puedes encontrar vínculos a las carpetas del repositorio para el módulo 3 (INICIAR) y el módulo 6 (FINALIZAR). También se puede acceder a ellos desde el repositorio de todas las migraciones de App Engine, que puedes clonar o descargar un archivo ZIP.
Codelab | Python 2 | Python 3 |
(código) | ||
Module 6 | (n/a) |
Recursos de App Engine
A continuación, se muestran recursos adicionales con respecto a esta migración específica:
- Referencias de Cloud Datastore y Cloud Firestore en Python
- Migra a Python 3 y GAE de entorno de ejecución de última generación
- General