Capítulo 9 — Colecciones, documentos y tipos de datos en Cloud Firestore¶
Recursos visuales propuestos¶
Antes de desarrollar este capítulo conviene definir con precisión qué recursos visuales realmente ayudarán al lector. En Firestore, muchas ideas fundamentales se comprenden mejor al ver estructuras simples y ejemplos concretos; por eso, la mayor parte del apoyo visual debe resolverse con imágenes didácticas. Los diagramas SVG deben reservarse para relaciones jerárquicas completas o comparaciones estructurales donde una imagen sencilla ya no sea suficiente.
Imágenes didácticas¶
- Representación visual de una colección. Conviene como imagen didáctica porque ayuda a entender de forma inmediata que una colección es un contenedor de documentos y no un registro con campos propios.[cite:1]
- Relación entre colección y documento. Es mejor como imagen didáctica porque el objetivo es pedagógico: mostrar el patrón alternado colección → documento → colección → documento.[cite:1]
- Ejemplos de documentos reales. También se recomienda como imagen didáctica porque el lector necesita ver cómo se parece un documento a un objeto JSON ligero con campos y valores.[cite:1]
- Comparación entre objetos embebidos y subcolecciones. Esta comparación funciona muy bien como imagen didáctica porque resume ventajas y limitaciones en un solo vistazo, especialmente cuando se contrasta dato pequeño y fijo frente a dato creciente.[cite:2]
- Tipos de datos soportados por Firestore. Conviene como imagen didáctica porque es un mapa conceptual claro: string, number, boolean, timestamp, geopoint, bytes, null, arrays, maps y references.[cite:3]
Diagramas SVG¶
- Arquitectura jerárquica completa de Firestore. Aquí sí conviene SVG porque debe mostrar la estructura completa de colecciones, documentos y subcolecciones con varios niveles y relaciones de navegación.
- Relaciones entre colecciones, documentos y subcolecciones. Se recomienda como SVG porque necesita precisión técnica para mostrar rutas, profundidad y alternancia estructural.[cite:1]
- Comparación entre distintos modelos de organización. Conviene SVG cuando se quieren comparar lado a lado una organización plana, una jerárquica y una híbrida dentro del mismo sistema.[cite:2]
- Estructura completa de datos del proyecto oficial del libro. Debe ser SVG porque integra varias colecciones y decisiones de diseño que el lector probablemente querrá revisar y reinterpretar durante capítulos posteriores.
Objetivos de aprendizaje¶
Al finalizar este capítulo, el lector será capaz de:
- Comprender con precisión qué son las colecciones, los documentos y las subcolecciones dentro del modelo documental de Firestore.[cite:1]
- Diferenciar cuándo conviene usar campos simples, objetos embebidos, arrays o subcolecciones según crecimiento, costo y facilidad de mantenimiento.[cite:2][cite:3]
- Identificar los tipos de datos soportados por Firestore y entender sus implicaciones técnicas, incluyendo tamaño, precisión, orden y comportamiento general.[cite:3]
- Elegir entre IDs automáticos e IDs personalizados con criterios arquitectónicos y operativos.[cite:1]
- Aplicar convenciones de organización y nomenclatura para construir una base de datos profesional, escalable y comprensible.
- Diseñar ejemplos reales de documentos del proyecto oficial del libro utilizando criterios consistentes.
Introducción¶
Cloud Firestore organiza la información con un modelo documental. Eso significa que no trabaja con tablas y filas como una base de datos relacional tradicional, sino con documentos agrupados en colecciones.[cite:1] Esta idea parece simple al principio, pero en la práctica determina casi todas las decisiones importantes de diseño: cómo se almacenan entidades, cómo crecen los datos, cuánto cuesta leerlos y qué tan fácil será mantener el sistema con el paso del tiempo.
La documentación oficial describe a Firestore como una base de datos NoSQL orientada a documentos, donde cada documento contiene pares clave-valor y las colecciones actúan como contenedores de esos documentos.[cite:1] También aclara que los documentos pueden incluir objetos anidados y subcolecciones, lo que da una enorme flexibilidad estructural.[cite:1][cite:2] Esa flexibilidad es poderosa, pero exige criterio. Una estructura mal elegida no solo complica la comprensión del sistema: también puede degradar rendimiento, incrementar costo y volver más difícil la evolución del producto.
En el capítulo anterior se estudió cómo modelar profesionalmente una base de datos en Firestore. Ahora toca descender a la capa estructural concreta. El objetivo de este capítulo es que el lector domine con profundidad la anatomía de Firestore: qué es una colección, qué es un documento, cómo se construye una jerarquía, qué tipos de datos existen y cuáles son las decisiones más sensatas para almacenar información real en una aplicación profesional.
Desarrollo completo¶
¿Qué es una colección?¶
Una colección es un contenedor de documentos. No almacena directamente campos con valores y no puede contener otra colección de forma directa; su función es agrupar documentos que pertenecen a un mismo conjunto lógico.[cite:1] Esta definición es muy importante porque mucha gente, al comenzar, interpreta la colección como si fuera una “tabla NoSQL”. Esa analogía puede servir de manera introductoria, pero es incompleta. Una colección no tiene columnas fijas ni un esquema rígido obligatorio.[cite:1]
La documentación oficial explica que una colección existe implícitamente cuando se crea el primer documento dentro de ella y deja de existir cuando ya no contiene documentos.[cite:1] Esta característica refuerza una idea clave: en Firestore la unidad primaria de vida real no es la colección sino el documento. La colección es el marco organizativo donde esos documentos viven.
En una aplicación profesional, una colección debe representar un conjunto semánticamente coherente. usuarios, cursos, instituciones, grupos, tareas o archivos son buenos ejemplos. Una colección mal pensada suele delatarse rápido: mezcla tipos de entidades, nombres ambiguos o funciones poco claras.
¿Qué es un documento?¶
El documento es la unidad de almacenamiento en Firestore.[cite:1] La documentación lo describe como un registro ligero compuesto por campos, donde cada campo mapea una clave a un valor.[cite:1] En la práctica, un documento se parece a un objeto JSON, aunque con diferencias importantes: soporta tipos de datos adicionales y está sujeto a límites técnicos específicos.[cite:1][cite:3]
Un documento debe representar una unidad coherente de información. Si se está modelando usuarios, cada usuario será normalmente un documento. Si se trabaja con cursos, cada curso será un documento. El documento no es una carpeta ni una mini base de datos. Es una pieza concreta del dominio del negocio.
La documentación oficial subraya que Firestore está optimizado para almacenar grandes colecciones de documentos pequeños.[cite:1] Esta frase tiene consecuencias profundas. Firestore no premia documentos gigantes, hiperanidados o convertidos en contenedores de listas crecientes. Premia documentos ligeros, directos y funcionales.
Relación entre colecciones y documentos¶
La relación entre colección y documento es estructural y obligatoria: los documentos viven dentro de colecciones.[cite:1] No existe un documento “suelto” fuera de una colección. Tampoco se pueden guardar campos directamente en la colección. La secuencia siempre alterna colección → documento → colección → documento.[cite:1]
Este patrón alternado define toda la arquitectura de Firestore. Si se quiere acceder a usuarios/alovelace, se está indicando una colección (usuarios) y luego un documento (alovelace). Si después se accede a usuarios/alovelace/notificaciones/abc123, se continúa la alternancia con subcolección (notificaciones) y nuevo documento (abc123).[cite:1]
Comprender este patrón evita muchísimos errores conceptuales. Firestore no permite documento dentro de documento ni colección dentro de colección sin pasar por la alternancia correspondiente.[cite:1] Esa restricción, lejos de ser una limitación arbitraria, ayuda a mantener una estructura clara y navegable.
¿Qué es una subcolección?¶
Una subcolección es una colección asociada a un documento específico.[cite:1] Su función es organizar datos hijos o contextuales cuyo crecimiento o ciclo de vida hace poco conveniente guardarlos dentro del documento padre.
La documentación oficial usa el ejemplo clásico de una aplicación de chat: rooms/{roomId}/messages/{messageId}.[cite:1] El razonamiento es muy ilustrativo. Un documento de sala de chat no debería contener todos los mensajes como campos o arrays si el número de mensajes puede crecer mucho. La subcolección permite que el documento principal siga siendo ligero mientras el conjunto hijo crece de forma independiente.[cite:1][cite:2]
En términos prácticos, una subcolección convierte una relación jerárquica en una estructura explícita y escalable. También facilita que el sistema siga siendo legible: es intuitivo entender que los mensajes pertenecen a una sala, que las notificaciones pertenecen a un usuario o que las clases pertenecen a un curso.
¿Cuándo utilizar subcolecciones?¶
La guía oficial de estructura de datos recomienda subcolecciones cuando los datos pueden expandirse con el tiempo.[cite:2] Esa recomendación es central. Si una lista es pequeña, fija y estable, podría vivir como dato embebido dentro del documento. Pero si ese conjunto crecerá o requerirá acceso propio, la subcolección suele ser más adecuada.[cite:2]
Las subcolecciones tienen varias ventajas oficiales claras:
- El tamaño del documento padre no cambia aunque la lista hija crezca.[cite:2]
- Se obtienen capacidades completas de consulta sobre la subcolección.[cite:2]
- Es posible realizar consultas de grupo sobre subcolecciones del mismo nombre en distintos documentos.[cite:2]
También tienen una limitación práctica relevante: no es fácil eliminar subcolecciones completas como si fueran simples campos.[cite:2] Esto significa que una subcolección no debe elegirse solo por estética estructural. Debe elegirse porque responde mejor al patrón de acceso y crecimiento del dato.
Campos y atributos¶
En Firestore, los datos dentro de un documento se almacenan en campos. Cada campo tiene un nombre y un valor.[cite:1] A nivel práctico, cuando en este manual se hable de atributos de una entidad, casi siempre se estará hablando de campos del documento.
Los campos pueden ser simples o complejos. Un nombre, un estado, un activo, una fechaCreacion o un rol son ejemplos de campos simples. Un objeto direccion, un mapa configuracionUI o un array etiquetas ya pertenecen a tipos estructurados más complejos.[cite:3]
La documentación indica que Firestore es esquemaless, es decir, no obliga a que todos los documentos de una colección tengan exactamente los mismos campos.[cite:1] Sin embargo, también aclara que conviene mantener consistencia de campos y tipos a través de documentos similares para facilitar consultas y organización.[cite:1] Esta recomendación, aunque parezca obvia, es una práctica profesional crítica.
Tipos de datos soportados por Firestore¶
La referencia oficial de tipos soportados enumera los tipos de datos disponibles en Cloud Firestore.[cite:3] Entre ellos se encuentran arrays, boolean, bytes, fecha y hora, números de punto flotante, enteros, mapas, null, references, strings, geopoints y vector embeddings.[cite:3] Para este capítulo se cubrirán los tipos solicitados por el temario y los más relevantes para aplicaciones tradicionales.
No basta con conocer sus nombres. También hay que entender sus implicaciones: tamaño, precisión, ordenamiento, legibilidad y uso recomendable.
Strings¶
Los strings o cadenas de texto representan texto codificado en UTF-8.[cite:3] Firestore permite almacenar cadenas bastante grandes, hasta 1,048,487 bytes, es decir, 1 MiB menos 89 bytes.[cite:3] Sin embargo, la documentación también aclara que en consultas solo se consideran los primeros 1,500 bytes de la representación UTF-8.[cite:3]
Esto tiene implicaciones importantes. Un string puede almacenar nombres, correos, títulos, descripciones cortas, URLs o estados textuales. Pero no conviene pensar en él como contenedor universal de texto ilimitado. Si una aplicación va a guardar textos enormes, conviene evaluar si realmente deben residir en Firestore o si otra estrategia sería más sensata.
En el proyecto del libro, strings serán el tipo dominante para nombres de usuarios, títulos de cursos, descripciones de tareas, nombres de instituciones y rutas lógicas de archivos.
Numbers¶
Firestore soporta enteros de 64 bits con signo y números de punto flotante de doble precisión IEEE 754.[cite:3] Además, la documentación indica que enteros y flotantes se ordenan conjuntamente en orden numérico y que los NaN se normalizan y consideran menores que -Infinity.[cite:3]
En la práctica, los números sirven para contadores, calificaciones, porcentajes, duraciones, posiciones, montos y prioridades. La decisión entre entero y flotante no es decorativa. Si una calificación puede tener decimales, flotante. Si el valor es un contador discreto, entero.
Una buena práctica profesional es usar el tipo numérico más coherente con el dominio y evitar mezclar representaciones sin motivo. Si en unos documentos una calificación es string y en otros número, el sistema se vuelve inconsistente y difícil de tratar.
Boolean¶
El booleano representa valores lógicos true y false.[cite:3] Es uno de los tipos más sencillos, pero también uno de los más útiles. Sirve para estados binarios como activo, publicado, verificado, archivado, completado o eliminadoLogicamente.
Su principal fortaleza es la claridad. Un campo booleano bien nombrado comunica intención rápidamente. Por ejemplo, esVisible, requiereRevision o aceptoTerminos son mucho mejores que strings ambiguos como estado = 'si'.
A nivel de diseño, los booleanos ayudan a evitar códigos innecesarios para estados que realmente solo tienen dos posibilidades. Cuando el dominio crece más allá de dos estados, probablemente conviene pasar a un string o enumeración lógica representada como texto.
Timestamp¶
Firestore soporta valores de fecha y hora con precisión de microsegundos; cualquier precisión adicional se redondea hacia abajo.[cite:3] Este tipo es fundamental para auditoría, orden temporal, vencimientos, programación de clases, fechas de entrega y seguimiento de actividad.
Un error frecuente es almacenar fechas como strings por comodidad visual. Eso suele ser una mala idea. El timestamp existe precisamente para representar tiempo con semántica temporal adecuada. Usarlo correctamente simplifica operaciones posteriores y mantiene consistencia en el modelo.
En una aplicación profesional, prácticamente toda entidad importante debería incluir timestamps como createdAt, updatedAt y, según el caso, publishedAt, dueAt, submittedAt o lastLoginAt.
GeoPoint¶
GeoPoint representa una ubicación geográfica mediante latitud y longitud.[cite:3] La referencia oficial también señala que para búsquedas basadas en distancia se deben usar estrategias geoespaciales específicas.[cite:3]
No todas las aplicaciones Firebase necesitarán GeoPoint, pero es muy útil cuando existe localización física: sedes, instituciones, aulas distribuidas, entregas georreferenciadas o eventos presenciales. En el proyecto del libro, podría servir para almacenar la ubicación de una institución o campus.
Su uso debe responder a una necesidad real. Guardar coordenadas “por si acaso” no aporta valor si el sistema nunca hará nada con ellas.
Bytes¶
El tipo bytes permite almacenar datos binarios, con el mismo límite máximo que strings: 1,048,487 bytes.[cite:3] La documentación aclara además que en consultas solo se consideran los primeros 1,500 bytes.[cite:3]
En la mayoría de aplicaciones profesionales, no conviene usar Firestore para almacenar binarios significativos como archivos completos, imágenes o PDFs. Para eso existe Cloud Storage. El tipo bytes es más útil para valores pequeños como huellas, hashes, tokens binarios o fragmentos específicos.
La regla práctica es sencilla: si algo parece un archivo, probablemente no deba vivir como bytes dentro de Firestore. Firestore debe almacenar metadatos, no el archivo pesado en sí.
Null¶
El valor null representa ausencia explícita de valor.[cite:3] Es diferente de “campo inexistente”, aunque en el diseño cotidiano ambos conceptos a veces se confunden.
Null puede ser útil cuando se quiere expresar que un dato fue contemplado pero aún no tiene contenido, como fechaRevision = null o docenteAsignado = null. Sin embargo, usar null masivamente también puede hacer el modelo más ruidoso.
En diseño profesional, conviene decidir si un campo opcional debe omitirse cuando no existe o si debe estar presente con valor null. Ambas estrategias pueden ser válidas, pero lo importante es mantener consistencia.
Arrays¶
Los arrays representan listas ordenadas de valores.[cite:3] La documentación aclara dos cosas muy importantes: un array no puede contener otro array como elemento y sus elementos mantienen la posición asignada.[cite:3]
Los arrays son útiles para listas pequeñas y controladas: etiquetas, categorías, permisos simples, idiomas, opciones visibles o un conjunto corto de identificadores relacionados. La guía de estructura de datos advierte, sin embargo, que los datos anidados y listas dentro del documento son menos escalables si crecen con el tiempo, porque el documento también crece y puede hacerse más lento de recuperar.[cite:2]
Esta advertencia debe tomarse muy en serio. Un array grande y creciente suele ser señal de que esa información necesita convertirse en subcolección o colección propia.
Objetos (Map)¶
Firestore llama map a lo que en desarrollo cotidiano suele entenderse como objeto embebido o estructura anidada.[cite:3] Un map representa un objeto dentro del documento, con claves internas y valores.[cite:3] La referencia oficial indica además que las claves se ordenan y que, cuando el campo se indexa, se puede consultar sobre subcampos.[cite:3]
Los objetos embebidos son excelentes para agrupar información pequeña y cohesionada. Una dirección, un bloque de configuración visual, metadatos compactos de auditoría o un resumen estructurado son buenos candidatos.
La guía oficial de estructura de datos considera que objetos complejos como arrays o maps dentro de documentos pueden ser una opción sencilla y útil para datos simples y fijos, aunque menos escalable si esos datos crecen con el tiempo.[cite:2] En consecuencia, un objeto embebido debe resolver simplicidad, no esconder una necesidad de estructura mayor.
DocumentReference¶
El tipo reference representa la ubicación de otro documento dentro de la base de datos y se ordena por los elementos de su ruta.[cite:3] A nivel de SDK, una referencia es un objeto ligero que apunta a una ubicación y puede crearse incluso si el documento no existe; crearla no realiza operaciones de red.[cite:1]
Desde el punto de vista del modelado, DocumentReference es valioso cuando una entidad necesita apuntar a otra sin duplicar todo su contenido. Una tarea puede apuntar al curso; una evidencia puede apuntar al alumno; un archivo puede apuntar al recurso propietario.
El uso de referencias debe ser consciente. Las referencias ayudan a preservar relaciones limpias, pero si una pantalla depende de demasiadas referencias encadenadas para mostrar información básica, el diseño puede requerir duplicación selectiva adicional.
Document ID¶
Todo documento está identificado por su ubicación y por su nombre dentro de la colección.[cite:1] Ese identificador no es un campo más: forma parte de la identidad estructural del documento. Por eso, cuando se habla de Document ID, se habla de la clave con la que el documento existe dentro de la colección.
El ID puede ser generado automáticamente por Firestore o definido por la aplicación.[cite:1] Esta decisión debe tomarse con criterio porque afecta legibilidad, interoperabilidad, facilidad de integración y, en ciertos escenarios, distribución de escritura.
En proyectos profesionales, el ID también comunica intención. Usar el UID de Authentication como ID del documento usuarios/{uid} es una excelente práctica. Usar un slug estable para una configuración global también puede ser razonable. En cambio, usar nombres mutables o cadenas ambiguas como ID suele traer problemas de mantenimiento.
IDs automáticos¶
La documentación oficial explica que se puede dejar que Cloud Firestore cree IDs aleatorios automáticamente.[cite:1] Esta opción es muy útil cuando solo importa unicidad, no legibilidad humana.
Los IDs automáticos tienen varias ventajas:
- Reducen la probabilidad de colisiones.
- Evitan que el desarrollador tenga que gestionar la generación del identificador.
- Suelen ser apropiados para entidades creadas masivamente o sin identidad natural previa.
Para colecciones como tareas, evidencias, archivos o notificaciones, los IDs automáticos suelen ser una gran elección. En la mayoría de estos casos, el sistema necesita unicidad y buena independencia entre registros, no un nombre comprensible por humanos.
IDs personalizados¶
Los IDs personalizados se usan cuando existe una clave natural o una necesidad operativa clara. Firestore permite proporcionarlos directamente.[cite:1] Ejemplos típicos son el UID de un usuario autenticado, el código de una institución o el identificador fijo de una configuración global.
Su principal ventaja es la legibilidad y la facilidad de integración con otros sistemas. Su principal riesgo es el acoplamiento: si el identificador semántico cambia o deja de ser adecuado, el sistema puede complicarse.
Por eso, la regla profesional es sencilla: usar IDs personalizados solo cuando realmente existe una identidad natural estable o una razón operacional fuerte.
Tamaño máximo de documentos¶
La documentación oficial sobre tipos soportados deja ver un límite importante: strings y bytes pueden llegar hasta 1,048,487 bytes, es decir, 1 MiB menos 89 bytes.[cite:3] Este mismo orden de magnitud remite al límite práctico del tamaño de un documento. Además, la documentación del modelo de datos insiste en que los documentos deben ser ligeros.[cite:1]
Desde el punto de vista arquitectónico, no hay que diseñar “hasta el límite”. El hecho de que un documento pueda acercarse a 1 MiB no significa que sea deseable. Firestore funciona mejor con documentos pequeños, claros y enfocados.[cite:1]
Cuando un documento empieza a incorporar listas crecientes, mapas enormes, textos muy extensos o metadatos excesivos, el diseño debe revisarse. Muchas veces ese crecimiento indica que parte de la información merece vivir en subcolecciones o en colecciones independientes.
Límites de Firestore¶
Además del tamaño práctico de los documentos, Firestore impone otros límites importantes. La documentación del modelo de datos indica que se puede anidar información hasta 100 niveles de profundidad.[cite:1] La referencia de tipos añade restricciones específicas, como el hecho de que arrays no pueden contener arrays y que los strings y bytes tienen límites máximos concretos.[cite:3]
Estos límites deben entenderse como guías técnicas y no como objetivos de diseño. Que Firestore permita 100 niveles de anidación no significa que una base bien diseñada deba acercarse a esa profundidad. Una arquitectura demasiado profunda suele ser más difícil de comprender, navegar y mantener.
El arquitecto profesional usa los límites para evitar errores, no para explorar el extremo de la tolerancia técnica del sistema.
Organización jerárquica¶
La organización jerárquica usa documentos y subcolecciones para reflejar relaciones de pertenencia fuertes. Es ideal cuando una entidad hija existe principalmente en el contexto de una entidad padre: por ejemplo, cursos/{cursoId}/clases/{claseId} o usuarios/{uid}/notificaciones/{notificacionId}.
Esta estructura mejora claridad contextual y mantiene el documento padre pequeño aunque la colección hija crezca.[cite:2] Además, comunica muy bien la lógica del dominio: una clase pertenece a un curso; una notificación pertenece a un usuario.
Su principal desventaja es que, si el sistema empieza a necesitar consultas muy transversales sobre esos hijos, la jerarquía puede requerir más planeación o estrategias complementarias. Por eso no toda entidad hija debe vivir siempre como subcolección.
Organización plana¶
La organización plana consiste en usar colecciones de nivel raíz para la mayoría de entidades: usuarios, cursos, tareas, evidencias, grupos, instituciones. La guía oficial indica que las colecciones raíz son especialmente buenas para relaciones muchos a muchos y proporcionan gran capacidad de consulta dentro de cada conjunto.[cite:2]
Su principal ventaja es la transversalidad. Una colección raíz se presta mejor para construir paneles globales, dashboards administrativos o vistas que combinan entidades desde varios contextos del sistema. Su principal desventaja es que puede perder parte del contexto natural de pertenencia.
En aplicaciones profesionales, la organización más efectiva suele ser híbrida: jerarquía donde la relación es fuerte y estable; organización plana donde la entidad necesita vivir de manera más transversal.
Convenciones para nombrar colecciones¶
Firestore no obliga a una convención de nombres, pero un proyecto profesional sí debe tenerla. La claridad en nombres reduce errores, simplifica mantenimiento y hace que el equipo piense el dominio de forma consistente.
Recomendaciones profesionales:
- Usar nombres estables y explícitos.
- Preferir un único idioma en todo el proyecto.
- Evitar abreviaturas oscuras.
- Mantener coherencia entre singular y plural.
- Nombrar según dominio, no según pantalla.
En este manual se usará español para coherencia editorial, con colecciones como usuarios, instituciones, grupos, cursos, tareas, evidencias y archivos. Lo importante no es el idioma elegido, sino la consistencia.
Convenciones para nombrar documentos¶
Los nombres o IDs de documentos deben obedecer a criterios claros:
- Si el documento tiene identidad natural estable, usar ID personalizado.
- Si no la tiene, usar Auto ID.
- Evitar espacios, caracteres problemáticos o valores mutables como nombres visibles.
- No usar información excesiva en el ID si puede vivir como campo.
Un mal ID suele delatar un mal criterio. Por ejemplo, usar como ID de curso una cadena que mezcla año, nombre legible, grupo, docente y versión puede parecer útil al principio, pero complica mantenimiento. Es mejor separar identidad e información descriptiva.
Buenas prácticas de organización¶
Una organización profesional de datos en Firestore suele seguir estas reglas:
- Mantener documentos pequeños y cohesionados.[cite:1]
- Usar mapas para estructuras pequeñas que siempre se lean juntas.[cite:2][cite:3]
- Usar subcolecciones para listas crecientes o datos hijos con vida propia.[cite:2]
- Usar colecciones raíz para entidades transversales o relaciones complejas.[cite:2]
- Evitar arrays para conjuntos que crecerán mucho.[cite:2][cite:3]
- Mantener consistencia de nombres y tipos entre documentos similares.[cite:1]
- Diseñar cada estructura pensando en el costo de lectura, la escalabilidad y la claridad del dominio.
Errores comunes¶
Los errores más frecuentes al organizar datos en Firestore son estos:
- Tratar la colección como si tuviera campos propios.
- Crear documentos demasiado grandes porque “así todo queda junto”.[cite:1][cite:2]
- Usar arrays gigantes donde debería existir una subcolección.[cite:2]
- Crear una jerarquía profunda sin necesidad real.[cite:1]
- Mezclar tipos de datos inconsistentes para el mismo campo en documentos similares.[cite:1][cite:3]
- Abusar de IDs personalizados semánticos y mutables.
- Guardar binarios pesados en Firestore en lugar de usar Cloud Storage.
- No distinguir entre dato pequeño embebido y dato creciente con ciclo de vida propio.
Casos prácticos¶
Caso 1: usuario con configuración visual¶
Supongamos que cada usuario tiene nombre, correo y una pequeña configuración de interfaz con tema, idioma y preferencia de notificaciones.
Aquí conviene que la configuración visual viva como objeto embebido dentro del documento del usuario, por ejemplo:
{
"displayName": "Ana Torres",
"email": "ana@ejemplo.com",
"settings": {
"theme": "dark",
"language": "es",
"emailNotifications": true
}
}
Esta decisión es correcta porque la configuración es pequeña, estable y normalmente se lee junto al perfil.
Caso 2: curso con muchas clases¶
Supongamos ahora que un curso puede tener decenas o cientos de clases. Guardar todas las clases en un array o map dentro del documento del curso sería una mala decisión porque el documento crecería con el tiempo.[cite:2]
En este caso, la mejor opción es usar una subcolección:
cursos/{cursoId}cursos/{cursoId}/clases/{claseId}
Esta estructura mantiene el curso ligero y permite que las clases crezcan de manera independiente.[cite:2]
Caso 3: archivos asociados a múltiples entidades¶
Los archivos en el proyecto del libro pueden relacionarse con perfiles, tareas, evidencias o credenciales. Si se almacenaran siempre como subcolección de una única entidad, algunas consultas futuras serían más difíciles.
Por eso, una colección raíz archivos resulta más profesional. Cada documento puede incluir referencias o IDs de la entidad propietaria y metadatos relevantes. Esta decisión favorece transversalidad y reutilización.
Ejemplos reales¶
A continuación se muestran ejemplos documentales orientados al proyecto oficial del libro.
Ejemplo 1: documento de usuario¶
Ruta: usuarios/uid_9x8a7b6c
{
"displayName": "Laura Mendoza",
"email": "laura@institucion.edu",
"photoURL": "https://...",
"rol": "docente",
"activo": true,
"institucionId": "inst_centro_digital",
"settings": {
"theme": "light",
"language": "es-MX",
"pushEnabled": true
},
"createdAt": "Timestamp",
"updatedAt": "Timestamp"
}
Justificación: el documento agrupa identidad, estado y configuración básica. Todo esto suele leerse junto. No incluye listas crecientes ni historial pesado.
Ejemplo 2: documento de institución¶
Ruta: instituciones/inst_centro_digital
{
"nombre": "Centro Digital Los Olivos",
"slug": "centro-digital-los-olivos",
"tipo": "secundaria",
"activa": true,
"direccion": {
"calle": "Av. Principal 100",
"ciudad": "Guadalajara",
"estado": "Jalisco",
"pais": "MX"
},
"ubicacion": "GeoPoint",
"createdAt": "Timestamp",
"updatedAt": "Timestamp"
}
Justificación: aquí un objeto embebido para dirección tiene sentido porque es pequeño y cohesionado. GeoPoint se reserva para ubicación geográfica real.[cite:3]
Ejemplo 3: documento de curso¶
Ruta: cursos/curso_auto_ab12cd34
{
"titulo": "Matemáticas Aplicadas I",
"descripcion": "Curso introductorio de razonamiento matemático.",
"institucionId": "inst_centro_digital",
"docenteId": "uid_9x8a7b6c",
"docenteResumen": {
"displayName": "Laura Mendoza",
"photoURL": "https://..."
},
"estado": "publicado",
"grados": ["1A", "1B"],
"activo": true,
"createdAt": "Timestamp",
"updatedAt": "Timestamp"
}
Justificación: se usa array para un conjunto pequeño y controlado de grados. También se incluye un resumen del docente para reducir lecturas en vistas frecuentes.
Ejemplo 4: documento de clase en subcolección¶
Ruta: cursos/curso_auto_ab12cd34/clases/clase_01
{
"titulo": "Números enteros",
"orden": 1,
"fechaProgramada": "Timestamp",
"duracionMinutos": 45,
"publicada": true,
"createdAt": "Timestamp"
}
Justificación: la clase vive como subcolección porque pertenece naturalmente al curso y puede crecer sin inflar el documento principal.[cite:2]
Ejemplo 5: documento de evidencia¶
Ruta: evidencias/evid_auto_x9k2p1
{
"tareaId": "tarea_auto_88k1",
"alumnoId": "uid_alumno_77z",
"cursoId": "curso_auto_ab12cd34",
"archivoId": "archivo_auto_q1w2",
"estado": "entregada",
"comentario": "Actividad completada en tiempo.",
"submittedAt": "Timestamp",
"reviewedAt": null
}
Justificación: la evidencia se modela como colección raíz porque puede necesitar consultas por tarea, alumno, curso o estado. reviewedAt puede comenzar en null hasta que haya revisión.[cite:3]
Ejemplo 6: documento de configuración global¶
Ruta: configuraciones/sistema
{
"mantenimiento": false,
"versionMinimaApp": "1.0.0",
"modulosActivos": {
"tareas": true,
"credenciales": true,
"notificaciones": true
},
"updatedAt": "Timestamp"
}
Justificación: un documento global con ID estable y personalizado es razonable cuando se trata de configuración única del sistema.
Buenas prácticas¶
- Mantener el patrón mental básico: colección → documento → colección → documento.[cite:1]
- Recordar que los documentos son la unidad de almacenamiento y deben ser ligeros.[cite:1]
- Utilizar mapas para estructuras pequeñas y estables.[cite:2][cite:3]
- Utilizar subcolecciones cuando el conjunto crecerá y no debe inflar el documento padre.[cite:2]
- Mantener consistencia de nombres y tipos de campos entre documentos comparables.[cite:1][cite:3]
- Preferir Cloud Storage para archivos reales y Firestore para metadatos.
- Elegir IDs personalizados solo cuando realmente aporten valor.
- Diseñar la organización no solo por elegancia conceptual, sino por costo de lectura y escalabilidad.
Errores comunes¶
- Confundir colección con documento.
- Guardar demasiada información en un solo documento.[cite:1]
- Elegir arrays por comodidad aunque el conjunto crecerá mucho.[cite:2]
- Crear subcolecciones para todo sin pensar si la entidad necesita vivir de forma transversal.
- Usar strings donde debería usarse timestamp, boolean o geopoint.[cite:3]
- Guardar archivos binarios grandes como bytes en Firestore.[cite:3]
- Nombrar colecciones y documentos sin convención clara.
- No justificar por qué una estructura es plana, jerárquica o híbrida.
Resumen¶
La estructura fundamental de Cloud Firestore se basa en documentos organizados dentro de colecciones, con posibilidad de extender la jerarquía mediante subcolecciones.[cite:1] Comprender esta base es indispensable porque todo el sistema de almacenamiento y acceso gira alrededor del patrón alternado colección → documento → colección.[cite:1]
Los documentos deben ser ligeros, coherentes y bien enfocados, mientras que las subcolecciones resultan especialmente útiles cuando un conjunto de datos crecerá con el tiempo.[cite:1][cite:2] Los objetos embebidos y arrays son útiles para datos pequeños y estables, pero dejan de ser recomendables cuando el contenido se vuelve grande o altamente dinámico.[cite:2][cite:3]
Además, Firestore ofrece un conjunto rico de tipos de datos —strings, números, booleanos, timestamps, geopoints, bytes, null, arrays, maps y references— que deben elegirse con criterio técnico y semántico.[cite:3] Un uso profesional de estos tipos mejora claridad, rendimiento, costo y mantenibilidad del sistema.
Conceptos clave¶
- Colección.[cite:1]
- Documento.[cite:1]
- Subcolección.[cite:1]
- Patrón alternado colección-documento.[cite:1]
- Objeto embebido o map.[cite:3]
- Array.[cite:3]
- DocumentReference.[cite:1][cite:3]
- Timestamp.[cite:3]
- GeoPoint.[cite:3]
- IDs automáticos.[cite:1]
- IDs personalizados.[cite:1]
- Organización jerárquica.[cite:2]
- Organización plana.[cite:2]
- Documento ligero.[cite:1]
- Límite práctico de tamaño.[cite:3]
Preguntas de repaso¶
- ¿Qué diferencia esencial existe entre una colección y un documento en Firestore?[cite:1]
- ¿Por qué Firestore obliga a seguir el patrón alternado colección → documento → colección?[cite:1]
- ¿Cuándo conviene utilizar una subcolección en lugar de un array u objeto embebido?[cite:2]
- ¿Qué ventajas y limitaciones tienen los maps dentro de un documento?[cite:2][cite:3]
- ¿Por qué los documentos deben mantenerse ligeros?[cite:1]
- ¿Qué tipos de datos nativos ofrece Firestore y cuáles usarías más en el proyecto del libro?[cite:3]
- ¿En qué casos usarías un ID personalizado y en cuáles Auto ID?[cite:1]
- ¿Qué problemas puede causar guardar listas crecientes dentro de un solo documento?[cite:2]
- ¿Por qué no conviene usar Firestore para almacenar archivos pesados como bytes?[cite:3]
- ¿Cómo justificarías una organización híbrida entre colecciones raíz y subcolecciones en una aplicación educativa?
Ejercicios prácticos¶
- Diseña el documento
usuarios/{uid}para el proyecto del libro e identifica qué campos serían strings, booleans, timestamps, maps y references. - Propón dos alternativas para almacenar las clases de un curso: como array dentro del curso y como subcolección. Explica cuál es mejor y por qué.[cite:2]
- Diseña una colección
archivoscon metadatos suficientes para enlazar documentos de Cloud Storage a tareas, evidencias o credenciales. - Toma una entidad como
institucionesy decide qué atributos deberían ir como campos simples y cuáles como objeto embebido. - Diseña una estructura de notificaciones para el usuario y justifica si usarías subcolección o colección raíz.
- Revisa un documento de ejemplo del capítulo y reescríbelo aplicando otra convención de nombres coherente.
Bibliografía y referencias oficiales¶
- Modelo de datos de Cloud Firestore: https://firebase.google.com/docs/firestore/data-model [cite:1]
- Guía oficial para elegir una estructura de datos: https://firebase.google.com/docs/firestore/manage-data/structure-data [cite:2]
- Tipos de datos soportados por Cloud Firestore: https://firebase.google.com/docs/firestore/manage-data/data-types [cite:3]