スキップしてメイン コンテンツに移動

firestoreでAuto Incrementフィールドを作成

FirestoreでAuto Increment Fieldを作成

Firestoreで連番となるフィールドの作成方法を紹介します。
肝はFirestoreのtransactionを使って原子性(Atomicity)、一貫性(Consistency)、独立性(Isolation)を保証することです。
汎用的に使えるgenerateSequenceNumber関数を作成してみました。

  • manage_collection: 連番を生成するターゲットcollectionを管理するcollection名
  • target_collection: 連番を生成するターゲットとなるcollection名
  • numberField: 連番を生成したいフィールド名

を渡して使います。

function generateSequenceNumber(db, manage_collection, target_collection, numberField) {
  const docRef = db.collection(manage_collection).doc(target_collection);
  return db.runTransaction((transaction) => {
    return transaction.get(docRef).then((doc) => {
      if (!doc.exists) {
         transaction.set(docRef, { [numberField]: 1});
         return 1;
      }
      const newNumber = typeof doc.data()[numberField] === 'undefined' ? 1 : doc.data()[numberField] + 1;
      await transaction.update(docRef, { [numberField]: newNumber });
      return newNumber;
    });
  })
}
});

target_collectionのdocument追加時に連番(numberフィールド)を振る場合の使用例を下記に示します。

const db = admin.firestore();
// generateSequenceNumberの引数のcollection名やフィールド名は、管理しやすい名前を付けられれば、なんでもOKです。
generateSequenceNumber(db, 'manage_collection', 'target_collection', 'number')
.then((number) => {
  db.collection('target_collection').add({
    number: number,
    some_filed: 'some value', // 連番以外の他のフィールド
  });

補足

公式のドキュメントによると、Firestoreのtransactionの特徴としては下記があります。

  • getの後に、set、update、deleteの操作が必要。
  • transactionが更新されたdocumentをgetした場合は、transactionは失敗となり、再度そのtransactionが実行される。

コメント