ОНОВЛЕННЯ : Зараз існує документ про структурування даних . Також дивіться цей чудовий пост про структури даних NoSQL .
Основна проблема з ієрархічними даними, на відміну від RDBMS, полягає в тому, що це спокуса вкладати дані, оскільки ми можемо. Як правило, ви хочете певною мірою нормалізувати дані (як і в SQL), незважаючи на відсутність заяв і запитів приєднання.
Ви також хочете денормалізувати у місцях, де ефективність читання викликає занепокоєння. Це методика, яка використовується всіма масштабними програмами (наприклад, Twitter і Facebook), і хоча це суперечить нашим принципам DRY, це, як правило, необхідна особливість масштабованих програм.
Суть у тому, що ви хочете наполегливо працювати над написанням, щоб зробити читання легким. Логічні компоненти, які читаються окремо, зберігайте окремо (наприклад, для чатів, не розміщуйте повідомлення, метаінформацію про кімнати та списки членів у одному місці, якщо ви хочете пізніше повторити групи).
Основна відмінність даних у режимі реального часу Firebase від середовища SQL - запит даних. Немає простого способу сказати "ВИБРАТИ КОРИСТУВАЧІ, де X = Y", через характер даних у реальному часі (вони постійно змінюються, різко змінюються, узгоджуються тощо), що вимагає більш простої внутрішньої моделі, щоб не перевіряти синхронізованих клієнтів)
Простий приклад, ймовірно, встановить вас у правильному стані душі, тож ось:
/users/uid
/users/uid/email
/users/uid/messages
/users/uid/widgets
Тепер, оскільки ми перебуваємо в ієрархічній структурі, якщо я хочу повторити електронні адреси користувачів, я роблю щось подібне:
// 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));
Проблема такого підходу полягає в тому, що я щойно змусив клієнта завантажити всіх користувачів messages
і widgets
теж. Немає великого, якщо жодна з цих речей не налічує тисяч. Але велика справа для 10-ти користувачів з 5 к-повідомленнями кожен.
Тож оптимальна стратегія для ієрархічної структури в реальному часі стає більш очевидною:
/user_meta/uid/email
/messages/uid/...
/widgets/uid/...
Додатковим інструментом, що є надзвичайно корисним у цьому середовищі, є індекси. Створюючи індекс користувачів з певними атрибутами, я можу швидко імітувати SQL-запит, просто ітеруючи індекс:
/users_with_gmail_accounts/uid/email
Тепер, якщо я хочу, скажімо, отримувати повідомлення для користувачів gmail, я можу зробити щось подібне:
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));
Я запропонував деякі подробиці в іншому дописі про денормалізацію даних, тому перевірте і їх . Я бачу, що Френк вже опублікував статтю Ананта, тому я не повторюю це тут, але це також чудове прочитання.