💕

連打できるいいねボタンなどでfirestoreで数値型データをインクリメントする方法と注意点

2021/03/04に公開

概要

  • SNSサービスのライブ視聴の機能の開発をした際の対応の方法についてまとめる
  • DBはfirestoreを使用

仕様

  • いいねボタンを押した回数が、users/hoge/live/fugaドキュメントのlikeCountのフィールドに累積される

コード

  // いいね数の初期化
  this.likeCount = 0;
  
  // 256msごとにいいね数を書き込む
  this.debounceLike = _.debounce(async () => {
    var userId = 'hoge';
    var liveId = 'fuga';
    var ref = firebase.firestore().collection('users').doc(userId).collection('live').doc('liveId');
    var doc = await ref.get();
    // ドキュメントが存在している
    if (doc.exists) {
      await ref.update({likeCount: firebase.firestore.FieldValue.increment(this.likeCount)});
    }
    // ドキュメントがまだ存在していない
    else {
      await ref.set({likeCount: firebase.firestore.FieldValue.increment(this.likeCount)});
    }
    // いいね数をリセット
    this.likeCount = 0;
  }, 256);

  // いいねボタンが押された時に呼ばれる
  this.onLike = () => {
    ++this.likeCount;
    this.debounceLike();
  };

実装手順

_.debounce

  • 連打された時に、毎回DBに書き込みに行くのでは大変なので、何秒かの間に押された分をまとめて書き込むようにした
  • そのため、underscore.js_.debounceを使う
  • これは指定した時間の間に何回呼び出されたも1回しか実行しないようにしてくれる便利関数

累積されたいいね数をまとめてDBに書き込む

  • likeCountというフィールドに累積されたいいね数を追加して積み上げたい
  • 今回はfirebase.firestore.FieldValue.increment()というfirestoreの便利関数を使う
  • これに数値を渡してあげるとその分をインクリメントしてくれる
  • 今回はthis.likeCountというメンバ変数で累積されたいいね数を管理しているので、それを上記関数に渡してあげる
  • ただし、setだとインクリメントされずに上書きをしてしまうので、docを取得し、そのドキュメントが存在していればupdate、なければsetをするように分岐した
  • 自分はまだフロントエンドしかまともに勉強していないので、DBの基礎だったらすいません

まとめ

  • 非同期処理を呼び出す頻度と、DBに書き込む時の方法をまとめた
  • なるべくDBにリクエストをする頻度を減らさないと、重くなる
  • かといって全ての処理をdebounceすると見た目上の変化のスピードも遅くなるので、ボタンをクリックされる時に呼び出される関数はdebounceせず、非同期処理箇所だけdebounceにくるんだ
  • こうすることで、あとはいいねボタンをクリックされた時の処理の中でアニメーションをさせたり表示を切り替えたり、いろいろできる
  • 私的にはfieldValueのincrementのsetで累積できないのが知らなかったので、つまづく人がいるかも、と思いメモした次第
  • 皆さんも気をつけてください

Discussion