Javascript + Firebase Realtime DatabaseでSQLのWHERE IN 的なことをしたい

Javascript + Firebase Realtime DatabaseでSQLのWHERE IN 的なことをしたい:

※タイトルにWHERE IN 的なことをしたいと書いていますが実際にはWHERE INとはほど遠く複数クエリをFirebaseに投げています

※そもそもFirebase Realtime Database自体が初心者なため、データ構造から自信がありません。 また、Promiseも理解しきれておりません。 もっと良い方法がありましたらご教示頂けると幸いです。


前提

React+FirebaseでSPAを開発


困ったこと

  • あるユーザに紐付くデータ(モデル)が複数個ある
  • 紐付けは以下のようにモデルのIDで持っている
"users": { 
  "ID-USER-abcde": { 
    "username": "tanaka", 
    "data": { 
      "ID-DATA-ABCDE": true, 
      "ID-DATA-FGHIJ": true 
    } 
  }, 
  ..snip.. 
}, 
"data": { 
  "ID-DATA-ABCDE": { 
     "num": 3 
  }, 
  "ID-DATA-FGHIJ": { 
     "num": 5 
  }, 
  "ID-DATA-KLMNO": { 
     "num": 8 
  }, 
  ..snip.. 
} 
  • やりたいことはSQLでいう
SELECT * WHERE IN ("ID-DATA-ABCDE", "ID-DATA-FGHIJ"); 
  • しかしFirebase Realtime Databaseにそのようにクエリする方法はない


方針

  • 改めてFirebaseに用意されている関数を確認してみる。 orderByChild()、orderByKey()、orderByValue() / limitToFirst()、limitToLast()、startAt()、endAt()、equalTo() => やりたいことはできなさそう
  • dataを全部持ってきてクライアントでフィルタする => 流石にネットワーク効率が非効率的な気がする
  • userに対するdataはそこまで多くなる予定はないので、 一つ一つ取得する


やったこと

Reactで開発しており、全てのデータを取得してからstateを更新したかった。 => Promise.allを使った

firebase 
  .db 
  .ref("User's data") 
  .once('value') 
  .then(snapshot => { 
    const dataObject = snapshot.val() 
    // ["ID-DATA-ABCDE", "ID-DATA-FGHIJ"] にする 
    const dataIds = Object.keys(dataObject) 
 
    const promises = dataIds.map(v => 
      firebase 
        .db 
        .ref("data") 
        .once('value') 
    ) 
 
    // 全てのデータ取得が完了してからstateを更新する 
    Promise.all(promises).then(v => { 
      // [{"num": 3}, {"num": 5}] 
      const data = v.map(snapshot => snapshot.val()) 
      this.setState({ 
        data 
        loading: false 
      }) 
    }) 
  }) 
これでやりたかったことは実現できました。

const promisesPromise.all.thenの外にだせる気もするんだけどjavascript力が弱い...

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)