[解決済み] firebaseでデータを構造化するのに最適な方法は?
質問
firebaseを初めて使うのですが、データを構造化するのに最適な方法を教えてください。
私は簡単な例を持っています。
私のプロジェクトには、申請者と申請書があります。1人の申請者は複数のアプリケーションを持つことができます。この2つのオブジェクトをFirebase上でどのように関連付けることができますか?リレーショナルデータベースのように動作するのでしょうか?それとも、データ設計の面で全く異なるアプローチが必要でしょうか?
どのように解決するのですか?
アップデイト : 現在では doc が追加されました。 . また、この素晴らしい投稿を参照してください。 NoSQL データ構造 .
RDBMS とは対照的に、階層的なデータの主な問題は、データを入れ子にできるため、誘惑に駆られることです。一般に、結合文やクエリーがないにもかかわらず、データをある程度正規化したいものです (ちょうど SQL で行うように)。
また 非正規化 を非正規化する必要があります。これはすべての大規模なアプリ (たとえば Twitter や Facebook) で使用されている手法であり、DRY 原則には反しますが、一般にスケーラブルなアプリに必要な機能です。
ここでの要点は、読み取りを簡単にするために書き込みに力を入れたいということです。別々に読み込まれる論理的なコンポーネントは別々にします (たとえば、チャット ルームでは、メッセージ、ルームに関するメタ情報、およびメンバーのリストをすべて同じ場所に配置しないでください。)
FirebaseのリアルタイムデータとSQL環境の主な違いは、データのクエリです。データのリアルタイムの性質のために、"SELECT USERS WHERE 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
もあります。どれも何千という数でなければ大したことはありません。しかし、それぞれ 5k 以上のメッセージを持つ 10k 人のユーザーにとっては大きな問題です。
これで、階層的なリアルタイム構造に対する最適な戦略がより明らかになりました。
/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));
データの非正規化については、別のSOの記事でいくつかの詳細を提供しました。 を作成しましたので、そちらもご覧ください。 . FrankがAnantの記事を既に投稿しているようなので、ここでは繰り返しませんが、こちらも素晴らしい読み物です。
関連
-
[解決済み] FirebaseのapiKeyを公開しても大丈夫ですか?
-
[解決済み] Cloud FirestoreとFirebase Realtime Databaseの違いとは?
-
[解決済み】Firebaseのdevとprodの環境を分ける。
-
[解決済み】Firebase App '[DEFAULT]' が作成されていない - Flutter と Firebase で Firebase.initializeApp() を呼び出す。
-
[解決済み] Firebase Cloud FunctionのHTTPエンドポイントを保護し、Firebase認証ユーザーのみを許可するには?
-
[解決済み] プロバイダの取得ができない com.google.firebase.provider.FirebaseInitProvider
-
[解決済み] Firebaseアプリにコラボレーターを追加する方法とは?
-
[解決済み] どうしたら解決できますか?Error: Firebase プロジェクトのリストアップに失敗しました。詳細はfirebase-debug.logを参照してください。
-
[解決済み] 他の関数に影響を与えずに、いくつかの関数をCloud Functions for Firebaseにデプロイするには?
-
[解決済み] Java修飾語(abstract, final, public, static, etc.)の妥当な順番は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Firebase v3 updateProfile メソッド
-
[解決済み] エラーです。Objective-Cモジュール'Firebase'をビルドできませんでした。
-
[解決済み】Firebase App '[DEFAULT]' が作成されていない - Flutter と Firebase で Firebase.initializeApp() を呼び出す。
-
[解決済み] アプリを別のFirebaseアカウントに転送する
-
[解決済み] プロバイダの取得ができない com.google.firebase.provider.FirebaseInitProvider
-
[解決済み] Google Firestoreです。プロパティ値の部分文字列に対するクエリ (テキスト検索)
-
[解決済み] 他の関数に影響を与えずに、いくつかの関数をCloud Functions for Firebaseにデプロイするには?
-
[解決済み] firebase cliからアプリを切り替えるには?
-
[解決済み] Java修飾語(abstract, final, public, static, etc.)の妥当な順番は?
-
[解決済み] .firebase/hostingの目的は何ですか?ALPHANUM.cache