guardar - ¿Cuál es la mejor forma de estructurar datos en firebase?
guardar datos en firebase android (3)
Firebase no es como una base de datos relacional. Si quieres compararlo con algo, lo compararía con una base de datos jerárquica.
Recientemente, Anant escribió una excelente publicación en el blog de Firebase sobre la desnormalización de sus datos: https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html
De hecho, sugiero mantener la "ID" de cada aplicación como hija de cada solicitante.
Soy nuevo en Firebase y quiero saber cuál es la mejor manera de estructurar datos en él.
Tengo un ejemplo simple:
Hay solicitantes y aplicaciones en mi proyecto. 1 solicitante puede tener varias aplicaciones. ¿Cómo puedo relacionar estos 2 objetos en la base de fuego? ¿Funciona como una base de datos relacional? ¿O el enfoque debe ser completamente diferente en términos de diseño de datos?
Su escenario se ve como uno a muchos en el mundo relacional, según su ejemplo, un solicitante tiene muchas aplicaciones. Si llegamos a firebase nosql de la manera que se ve a continuación. Debería ampliarse sin problemas de rendimiento. Es por eso que necesitamos desnormalización como se menciona a continuación.
applicants:{
applicant1:{
.
.
applications:{
application1:true,
application3:true
}
},
applicant2:{
.
.
applications:{
application2:true,
application4:true
}
}}
applications:{
application1:{
.
.
},
application2:{
.
.
},
application3:{
.
.
},
application4:{
.
.
}}
ACTUALIZACIÓN : ahora hay un documento sobre la estructuración de datos . Además, vea esta excelente publicación sobre estructuras de datos NoSQL .
El problema principal con los datos jerárquicos, a diferencia de RDBMS, es que es tentador anidar datos porque podemos. En general, desea normalizar los datos en cierta medida (al igual que lo haría con SQL) a pesar de la falta de declaraciones y consultas de combinación.
También desea denormalize en lugares donde la eficiencia de lectura es una preocupación. Esta es una técnica utilizada por todas las aplicaciones a gran escala (por ejemplo, Twitter y Facebook) y, aunque va en contra de nuestros principios DRY, generalmente es una característica necesaria de las aplicaciones escalables.
Lo esencial aquí es que quieres trabajar duro en las escrituras para facilitar las lecturas. Mantenga los componentes lógicos que se leen por separado (por ejemplo, para las salas de chat, no coloque los mensajes, metainformación sobre las salas y listas de miembros, todo en el mismo lugar, si desea poder repetir los grupos más adelante).
La principal diferencia entre los datos en tiempo real de Firebase y un entorno SQL es la consulta de datos. No hay una forma simple de decir "SELECCIONE USUARIOS DONDE X = Y", debido a la naturaleza en tiempo real de los datos (cambia constantemente, fragmenta, reconcilia, etc., lo que requiere un modelo interno más simple para mantener a los clientes sincronizados bajo control)
Un ejemplo simple probablemente lo colocará en el estado mental correcto, así que aquí va:
/users/uid
/users/uid/email
/users/uid/messages
/users/uid/widgets
Ahora, dado que estamos en una estructura jerárquica, si quiero iterar las direcciones de correo electrónico de los usuarios, hago algo como esto:
// I could also use on(''child_added'') here to great success
// but this is simpler for an example
firebaseRef.child(''users'').once(''value'')
.then(userPathSnapshot => {
userPathSnapshot.forEach(
userSnap => console.log(''email'', userSnap.val().email)
);
})
.catch(e => console.error(e));
El problema con este enfoque es que acabo de forzar al cliente a descargar todos los messages
y widgets
de los usuarios. No hay problema si ninguna de esas cosas se cuenta en miles. Pero es un gran negocio para 10 mil usuarios con más de 5 mil mensajes cada uno.
Entonces, ahora la estrategia óptima para una estructura jerárquica en tiempo real se vuelve más obvia:
/user_meta/uid/email
/messages/uid/...
/widgets/uid/...
Una herramienta adicional que es extremadamente útil en este entorno son los índices. Al crear un índice de usuarios con ciertos atributos, puedo simular rápidamente una consulta SQL simplemente iterando el índice:
/users_with_gmail_accounts/uid/email
Ahora si quiero, por ejemplo, obtener mensajes para usuarios de gmail, puedo hacer algo como esto:
var ref = firebase.database().ref(''users_with_gmail_accounts'');
ref.once(''value'').then(idx_snap => {
idx_snap.forEach(idx_entry => {
let msg = idx_entry.name() + '' has a new message!'';
firebase.database().ref(''messages'').child(idx_entry.name())
.on(
''child_added'',
ss => console.log(msg, ss.key);
);
});
})
.catch(e => console.error(e));
Ofrecí algunos detalles en otra publicación de SO sobre desnormalización de datos, así que fíjate también en ellos . Veo que Frank ya publicó el artículo de Anant, así que no voy a reiterarlo aquí, pero también es una gran lectura.