Buscar..


Introducción

La base de datos de Firebase es una base de datos NoSQL que almacena sus datos en forma de objetos JSON jerárquicos. No hay tablas ni registros de ninguna forma como normalmente tendría una base de datos SQL, solo nodos que conforman una estructura de clave-valor.

Normalización de datos

Para tener una estructura de base de datos adecuadamente diseñada, los requisitos de los datos deben ser detallados y previsibles. La estructura en este caso debe normalizarse; Cuanto más plano sea el árbol JSON, más rápido será el acceso a los datos.

Normas

La forma incorrecta

Considere la siguiente estructura

{
  "users": {

    // Uniquely generated IDs for children is common practice,
    // it's actually really useful for automating child creation.
    // Auto-incrementing an integer for a key can be problematic when a child is removed.

    "-KH3Cx0KFvSQELIYZezv": {     
      "name": "Jon Snow",
      "aboutMe": "I know nothing...",
      "posts": {
        "post1": { 
          "body": "Different roads sometimes leads to the same castle", 
          "isHidden": false
        },
        "post2": { ... },
        // Possibly more posts
      }
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },     // Another user
    // A lot more users here
  }
}

Este es un gran ejemplo de lo que NO se debe hacer. Estructuras multi-anidadas como la anterior pueden ser muy problemáticas y podrían causar un enorme retroceso en el rendimiento.

La forma en que Firebase accede a un nodo es mediante la descarga de todos los datos de los niños, y luego iterando sobre todos los nodos del mismo nivel (los hijos de todos los padres). Ahora, imagine una base de datos con varios usuarios , cada uno con cientos (o incluso miles) de publicaciones . El acceso a una publicación en este caso podría potencialmente cargar cientos de megabytes de datos no utilizados. En una aplicación más complicada, el anidamiento podría ser más profundo que solo 4 capas, lo que resultaría en descargas e iteraciones más inútiles.

La manera correcta

Aplanando la misma estructura se vería así

{
  // "users" should not contain any of the posts' data
  "users": {
    "-KH3Cx0KFvSQELIYZezv": {
      "name": "Jon Snow",
      "aboutMe": "I know nothing..."
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },
    // More users
  },

  // Posts can be accessed provided a user key
  "posts": {
    "-KH3Cx0KFvSQELIYZezv": {     // Jon Snow's posts
      "post1": { 
        "body": "Different roads sometimes leads to the same castle", 
        "isHidden": false
      },
      "post2": { ... },
      // Possibly more posts
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },
    // other users' posts
  }
}

Esto ahorra una gran cantidad de sobrecarga al iterar sobre menos nodos para acceder a un objeto objetivo. Todos los usuarios que no tienen ninguna publicación no existirían en la rama de publicaciones , por lo que la iteración sobre los usuarios en la forma incorrecta anterior es completamente inútil.

Relaciones bidireccionales

El siguiente es un ejemplo de una base de datos universitaria simple y mínima que utiliza relaciones bidireccionales

{
  "students": {
    "-SL3Cs0KFvDMQLIYZEzv": {
      "name": "Godric Gryffindor",
      "id": "900130309",
      "courses": {
         "potions": true,
         "charms": true,
         "transfiguration": true, 
      }
    },
    "-SL3ws2KvZQLTYMqzSas": {          
      "name": "Salazar Slytherin",
      "id": "900132319",
      "courses": {
         "potions": true,
         "herbs": true,
         "muggleStudies": true, 
      }
    },
    "-SL3ns2OtARSTUMywqWt": { ... },
    // More students here
  },

  "courses": {
    "potions": {
      "code": "CHEM305",
      "enrolledStudents": {
        "-SL3Cs0KFvDMQLIYZEzv": true,     // Godric Gryffindor
        "-SL3ws2KvZQLTYMqzSas": true,     // Salazar Slytherin
        // More students
      }
    },
    "muggleStuddies": {
      "code": "SOC215",
      "enrolledStudents": {
        "-SL3ws2KvZQLTYMqzSas": true,     // Salazar Slytherin
        "-SL3ns2OtARSTUMywqWt": true,     // Some other student
        // More students
      }
    },
    // More courses
  }
}

Tenga en cuenta que cada estudiante tiene una lista de cursos y cada curso tiene una lista de estudiantes inscritos.

La redundancia no siempre es un mal enfoque. Es cierto que cuesta espacio de almacenamiento y tener que lidiar con la actualización de varias entradas al eliminar o editar un nodo duplicado; sin embargo, en algunos escenarios donde los datos no se actualizan con frecuencia, tener relaciones bidireccionales podría facilitar significativamente el proceso de búsqueda / escritura.

En la mayoría de los escenarios donde parece necesaria una consulta similar a SQL, la solución suele ser invertir los datos y crear relaciones bidireccionales.

Considere una aplicación que use la base de datos anterior que requiere la capacidad de:

  1. Listar los cursos que un estudiante determinado está tomando y ...
  2. Listar todos los alumnos en un determinado curso.

Si la estructura de la base de datos hubiera sido unidireccional, sería increíblemente más lento escanear o consultar uno de los dos requisitos anteriores. En algunos escenarios, la redundancia hace que las operaciones frecuentes sean más rápidas y mucho más eficientes, lo que, a largo plazo, hace que el costo de las duplicaciones sea insignificante.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow