LoginSignup
0
0

More than 5 years have passed since last update.

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

Posted at

※タイトルに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力が弱い...

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0