← Volver al blog Post

Estructurando datos en Cloud Firestore

Publicado originalmente en Medium.

Cloud Firestore es una de las bases de datos NoSQL que ofrece Firebase para almacenar la información de nuestras aplicaciones.

Cloud Firestore es una base de datos flexible y escalable para servidores, dispositivos móviles y web. Mantiene los datos sincronizados entre clientes, permite trabajar sin conexión y se integra con el resto del ecosistema Firebase y Google Cloud.

Durante mucho tiempo estuvo en beta, pero incluso en esa etapa ya resultaba suficientemente robusta como para usarse en aplicaciones reales. Aun así, igual que ocurre con cualquier base de datos, el éxito de una aplicación depende mucho del cuidado que pongamos en el diseño del modelo de datos.

En Firestore eso es especialmente importante: una estructura acertada hace que el sistema sea sencillo de consultar y securizar; una estructura deficiente puede convertir tareas simples en una fuente continua de frustración.

Qué nos permite Cloud Firestore

Cloud Firestore es una base de datos orientada a documentos. Si ya has trabajado con soluciones como MongoDB, gran parte del enfoque te resultará familiar.

La estructura general se basa en:

  • colecciones, que agrupan entidades del mismo tipo,
  • documentos, que viven dentro de esas colecciones,
  • y campos, que representan los atributos de cada documento.

Cada colección tiene un nombre. Cada documento tiene un identificador único. Y un detalle importante es que los documentos hermanos no tienen por qué compartir exactamente los mismos campos, aunque en la práctica normalmente querremos mantener cierta coherencia.

Primeros pasos en Firebase

Como Firestore forma parte del ecosistema de Firebase, el primer paso es acceder al servicio con una cuenta de Google:

https://console.firebase.google.com/

Una vez dentro podemos crear un proyecto nuevo o reutilizar uno ya existente. Si creamos uno nuevo, Firebase nos pedirá un nombre y una región.

La región no es un detalle menor. Puede afectar a la latencia, a los costes y al cumplimiento normativo, por ejemplo en cuestiones relacionadas con el RGPD.

Tras la creación del proyecto, el panel de Firebase da acceso a todos los servicios asociados. Para entrar en Firestore basta con ir a Database y elegir Cloud Firestore.

En ese momento también se nos pedirá un modo de seguridad inicial. Lo habitual es comenzar con el modo bloqueado, que niega el acceso directo a los datos hasta que definamos reglas más precisas.

Una vez dentro de Firestore

Cuando entramos en Firestore encontramos varias secciones, pero las más importantes para empezar son:

  • Datos
  • Reglas

La pestaña de datos materializa el modelo principal: colecciones que contienen documentos, y documentos que contienen campos.

Por ejemplo, una colección usuarios puede contener documentos individuales de usuario. Si consultamos usuarios, obtendremos la colección. Si consultamos usuarios/{id}, obtendremos un documento concreto.

Dentro de cada documento podemos guardar valores simples, objetos y también subcolecciones.

Qué son las subcolecciones y cuándo usarlas

Una subcolección es una colección anidada dentro de un documento concreto. Eso significa que queda asociada a ese documento y se accede a ella a través de su identificador.

Por ejemplo:

/usuarios/{userId}/[nombre-de-subcoleccion]

Una duda muy habitual es esta:

¿Qué aporta una subcolección que no aporte un objeto dentro del documento?

La respuesta más práctica está en los permisos y en la forma de acceso. Si un cliente tiene permiso para leer usuarios/{userId}, podrá ver todo lo que esté directamente dentro de ese documento. En cambio, una subcolección puede protegerse con reglas específicas y consumirse de forma separada.

Eso permite, por ejemplo, que determinada información sensible solo esté disponible para el propio usuario, aunque otras partes del documento principal sean visibles para más actores.

Reglas

Las reglas son uno de los puntos más potentes de Firestore. Con ellas definimos quién puede acceder a qué rutas y qué acciones puede realizar sobre cada una.

Firestore expone los datos siguiendo una estructura basada en rutas. Eso hace posible securizar el acceso de una manera bastante expresiva.

La configuracion inicial por defecto es esencialmente una denegacion total:

match /databases/{database}/documents {
  match /{document=**} {
    allow read, write: if false;
  }
}

Es decir, toda lectura y escritura queda bloqueada hasta que indiquemos lo contrario.

Las acciones principales que podemos controlar son:

  • create
  • read
  • update
  • delete

Y, por supuesto, podemos combinarlas según la ruta y las condiciones necesarias.

La documentación oficial de seguridad amplía todos estos casos:

https://firebase.google.com/docs/firestore/security/get-started?hl=es-419

Reglas más avanzadas

Las reglas no se limitan a abrir o cerrar una ruta de forma estática. También permiten expresar lógica más rica a partir del contenido de la solicitud y de los propios datos almacenados.

Imaginemos una colección users en la que cada documento contiene un objeto roles, con banderas booleanas como estas:

roles.subscriber
roles.editor
roles.admin

Con ese planteamiento podemos decidir que:

  • subscriber solo pueda leer,
  • editor pueda actualizar,
  • admin sea quien pueda crear y borrar.

La idea es apoyarse en request.auth.uid, recuperar el documento del usuario que realiza la petición y consultar ahí sus permisos antes de autorizar la operación.

El modelo mental sería algo así:

allow read: if hasRole('subscriber');
allow update: if hasRole('editor');
allow create, delete: if hasRole('admin');

Y sobre eso todavía podemos añadir una condición extra para exigir que el usuario esté autenticado antes de hacer cualquier comprobación de rol.

Conclusión

Cloud Firestore es una herramienta muy potente y limpia desde el punto de vista de la estructura y la configuración. Bien modelada, puede acelerar mucho el desarrollo de aplicaciones sencillas y medianas.

La clave está en no tratarla como un simple contenedor de documentos. Conviene dedicar tiempo a decidir:

  • cómo dividir colecciones y documentos,
  • cuándo usar subcolecciones,
  • y cómo expresar permisos a través de reglas.

Cuando esa base está bien pensada, el resto del trabajo resulta mucho más natural.

  • firebase
  • firestore
  • nosql