Google Firebase en iOS: Cloud Firestore

Hace unas semanas te habla de la importancia de que nuestras apps guarden sus datos en un servidor, no sólo para personalizar la experiencia de nuestros usuarios, sino también para mantener sus datos sincronizados entre dispositivos. Hoy te vengo a hablar de Firebase Cloud Firestore, la base de datos hermana mayor de la Realtime Database.

¿Qué es la Cloud Firestore?

Como te decía, Cloud Firestore es la base de datos de Firebase hermana mayor de la Realtime Database. ¿Y por qué digo esto? Porque puedes hacer todo lo que puedes hacer con la anterior, y un montón de cosas más.

Si hay algo que los ingenieros de Firebase hacen muy bien, es escuchar a los desarrolladores que usan sus herramientas. Pues bien, lo han seguido haciendo durante los últimos tiempos, y uno de los resultados de ello es, precisamente, Cloud Firestore. Te lo cuento.

 

Tipos de datos soportados

A diferencia de la realtime database (que sólo soportaba numéricos, strings y booleanos, y además no soportaba arrays), Cloud Firestore soporta: Arrays, booleanos, bytes, DateTime, numéricos, punto geográfico, mapas, nulos, referencias (paths a otros elementos), y por supuesto, strings. Casi nada.

Además, CF se basa en los conceptos de documentos y colecciones (de documentos) . Un documento es un objeto JSON soportando los tipos de datos que te menciono arriba. Los documentos, a su vez, pueden contener subcolecciones.

Ésto último supera la principal limitación que teníamos con la real time y es que con CF podemos hacer consultas sobre datos más profundos en la jerarquía que el propio nodo sobre el que estamos haciendo la consulta.

 

Recuperando datos de Cloud Firestore

La manera de obtener datos en Cloud Firestore es trivial, al igual que con la real time. Por ejemplo, si queremos recuperar el listado de usuarios, llamaríamos a

En el caso de Swift, proporcionamos un closure que nos da acceso a los datos recuperados de la base de datos: en este caso, un listado de documentos.

Si queremos acceder a un documento concreto dentro de una colección, usaríamos

Al igual que en el caso anterior, en un closure recibiremos los datos del documento solicitado.

También, de manera más sencilla, podemos acceder al documento directamente si sabemos su path completo con

Fácil, ¿no?

 

Escuchando cambios en tiempo real

Al igual que ocurría con la real time, con Cloud Firestore también podemos escuchar a cambios que ocurren en documentos y colecciones. Para escuchar cambios en un usuario concreto, usaríamos

Recogiendo en el closure un snapshot con los datos actuales.

También podemos escuchar los cambios que ocurren en varios documentos de una colección, filtrados por condición. Por ejemplo, con

recibiremos en un closure las adiciones, modificaciones, y los cambios que ocurran en todos los usuarios que se llamen “Koldo”. Podemos conocer si estas modificaciones han sido una adición, eliminación, o modificación dentro del closure.

 

Queries y filtrado

Imagina que queremos obtener un listado de usuarios filtrando por un campo concreto. Para filtrar los datos sobre colecciones, usamos los métodos “where” del SDK. Por ejemplo, para recuperar los usuarios que se llamen “Naiara” llamaríamos a

Los operadores de filtrado que podemos usar son isEqualTo, isLessThan, isGreaterThanOrEqualTo.

Una GRAN mejora respecto a la realtime son las queries compuestas. Podemos anidar queries con AND sobre diferentes valores, encadenando llamadas a “where”. Por ejemplo, la query

encadena dos “where”, de forma que nos devolvería todos los usuarios que se llamen Koldo, y que además tengan una edad mayor a 35.

En cuanto a la ordenación y límite de las queries, tenemos por supuesto la opción de hacerlo. De forma que

nos ejecutará una query que:

  • Se ejecuta sobre la colección “User”
  • Recupera los programadores de Swift
  • Ordena por nombre descendente
  • Si hay coincidencias los ordena por apellido ascendente
  • Limita el resultado a 3

 

Todo se declara de forma muy expresiva, y la verdad es que es muy cómo de usar.

 

Escribiendo datos en Cloud Firestore

Al igual que la lectura, la escritura de datos es también trivial. Llamando a “setData()” sobre el documento que queremos escribir es suficiente. Y aquí tenemos otra principal diferencia respecto a la real time: si queremos actualizar únicamente ciertos atributos del documento sin modificar el resto, tenemos que pasarle a setData el valor “merge” en el párametro “options”. Es decir, si queremos cambiar de apellido a un usuario de nuestra base de datos, manteniendo el resto del documento sin cambios, llamaríamos a

El equivalente a lo anterior si queremos actualizar sólo parte de un objeto sería usar

De esta forma nos ahorramos el parámetro options.

Para añadir un documento con ID automático a la base de datos, llamaríamos a

Una cosa super chula de la Cloud Firestore es que podemos actualizar objetos anidados usando “dot” notation. Por ejemplo, si uno de los campos de mi documento es un mapa clave-valor, y sólo quiero actualizar uno de los valores de ese mapa, usaría un punto para referenciarlo:

Transacciones

Tal y como ocurría en la RTDB, aquí también podemos hacer transacciones: bloques de operaciones que se ejecutan de forma atómica. Muy útiles, por ejemplo, cuando quieres incrementar un contador. Si ocurren operaciones que modifican los mismos datos mientras dura nuestra transacción, Firebase se encarga de volver a lanzarla hasta que lo consiga.

Por ejemplo, si queremos incrementar el número de asistencias de Jorge a Codemotion:

Se recomienda no modificar el estado de la app dentro de una transacción: recuerda que si la transacción falla, el código se volverá a ejecutar hasta que ésta sea exitosa.

Escrituras en lotes

Si no necesitamos realizar lecturas en ningún documento, podemos ejecutar escrituras de forma atómica. Dentro del batch podremos meter cualquier operación del tipo set, update, o delete.

Borrado de datos

El borrado de documentos es super trivial, simplemente llamaos al método delete sobre la referencia de un documento.

Si lo que queremos es borrar un campo de un documento, tendremos que ejecutar una update un poco especial, pues tenemos que asignar el valor FieldValue.delete() al campo que queremos borrar.

Sin embargo, no hay una forma sencilla de borrar una colección: hay que borrar todos los documentos contenidos en ella:

Seguridad

Al igual que te decía en el post sobre la RTDB, la seguridad es tan importante que merece un post aparte, así que no me dentedré mucho aquí.

Las reglas de seguridad se pueden añadir bien desde la consola de Firebase, o bien desde un fichero de reglas que se genera con la línea de comandos. Valga el siguiente ejemplo extraído de la documentación de Firebase para hacerte una idea de cómo configurar las reglas por documentos y colecciones:

 

Modo offline en Cloud Firestore

El modo sin conexión hace que nos olvidemos completamente de la sincronización de cambios que ocurrieron mientras el dispositivo estaba sin conexión. De forma automática, Cloud Firestore acomete los cambios necesarios por nosotros para llevar a cabo la sincronización cuando el dispositivo vuelve a estar conectado. Para activar la persistencia sólo hay que hacer esto:

Fácil, ¿no?

 

Gestión de presencia

Cloud Firestore no tiene gestión de presencia tal y como existía en la Realtime. La propuesta de Firebase para solucionar esto es precisamente apoyarse en la Realtime para implementar presencia en Firestore.

Habría que implementarlo en dos pasos. Primero, en el lado cliente, cada vez que el usuario se pone online/offline en la realtime database, actualizamos este estado también en Firestore. Cuando el usuario se pone offline, esto sólo tiene efecto en el lado cliente, no en el servidor. Por lo tanto hay que añadir además una cloud function que se lance cuando la realtime cambie el valor offline/online de un usuario, de forma que actualizamos el valor online/offline en Firestore.

 

Conexión con Cloud Functions

Al igual que con la Realtime, Firestore también proporciona Cloud Functions en forma de triggers que se ejecutarán cuando ocurre algún cambio en algún documento (ojo, no funciona en colecciones, sólo en documentos). Los triggers que podemos añadir son: onCreate, onDelete, onUpdate y onWrite.

¿Qué debo usar: la Realtime Database o Cloud Firestore?

Es una pregunta muy mencionada. Entonces, ¿qué tengo que usar, Realtime o Firestore? Uno de mis clientes acudió al úlitmo Firebase Dev Summit celebrado en Amsterdam, y les planteó la pregunta a los ingenieros de Google que estaban allí: la respuesta fue básicamente, que si aún no has publicado tu app utilices directamente Firestore, de lo contrario sigue con la Realtime y plantéate ir migrando con el tiempo.

Yo he utilizado mucho la Realtime y un poco la Firestore, y te puedo decir que la Firestore, a pesar de no gestionar presencia y tener que apoyarse en Realtime para esto, ofrece más tipos de datos, queries más complejas y profundas en la jerarquía, y una capacidad de normalización de datos mayor que con la Realtime.

Por último, ten en cuenta que Firestore aún está en fase beta (a Enero de 2018), y por tanto su API puede ser aún cambiante. Lo que sí es cierto, es que cuando se lance como producto acabado, ofrecerá más seguridad y será mejor en muchos aspectos que la Realtime.

Conclusión

Creo que en este post te he demostrado clarmente que Firestore es la base de datos “hermana mayor” de la Realtime. Ambas son bases de datos en tiempo real y con una estructura de datos similar, pero Firestore mejora en muchos aspectos: tipos de datos, queries y filtros más potentes, escalabilidad, y normalización de datos. Será la base de datos más promocionada por Firebase dentro de poco, en detrimento de la Realtime.

Si aún no has empezado a desarrollar tu app, o aún no la has publicado, olvida la Realtime y considera publicar con Firestore directamente. Si ya has publicado en Realtime y necesitas alguna función específica de la Firestore, tendrás que migrar. No obstante, ten en cuenta también que se pueden usar ambas bases de datos en el mismo proyecto.

Si te perdiste los últimos posts sobre Firebase, recuerda que ya te di una visión general, hablé de analytics, de autenticación, y de la realtime database anteriormente.

¿Y tú? ¿Qué base de datos usas en tu app? ¡Cuéntamelo en los comentarios!

 

No hay comentarios

Deja un comentario