nodejs
Firestore

firebaseのドキュメントが教えてくれないfirestore

P&Dのアドベントカレンダー7日目です。ちょうど1週間たったんかな?


先に言っておきます。

この記事はfirestore編しかないです!!


背景

僕は Nativeエンジニアちゃんなのでfirebaseを呼び出すときは単純に用意されているコールバック関数を呼ぶだけで大丈夫でした。

とある知り合いとNodeJSでfirebaseを使ってAPIサーバーを作ることになったのですが、初めて使うexpress、初めて使うjsでのfirestoreの呼び出しにやたら戸惑いました。最大の問題点は、firestore + expressの記事が一つも見当たらなかったことです。したがって、同じ思いで苦しんでいる人のために少しでも参考になればと思い書かせてもらうことにしました。


開発環境

nodejs: v10.10.0

express: 6.4.1


作っていたAPIの概要

ユーザーデータをfirestoreに追加、一覧の取得ができるAPIサーバーでした。

/usersのpostで新しいユーザーの追加

/usersのgetでユーザー一覧の取得


実装内容


全体の概要

usersのミドルウェアはroutes/user.jsに記述をしていたのですが、このような感じでした。


users.js

const admin = require('firebase-admin');

const functions = require('firebase-functions');
var sys = require('util');
var express = require('express');
var router = express.Router();

// setup firestore
admin.initializeApp(functions.config().firebase);
var db = admin.firestore();

/* Get user list */
router.get('/', function(req, res, next) {
db.collection('users').get()
.then((snapshot) => {
var users = new Array();
snapshot.forEach((doc) => {
users.push(doc.data());
});
res.json(users);
})
.catch((err) => {
next(err);
});
});
/* Post new user*/
router.post('/', function(req, res, next) {
var newData = req.body
var docRef = db.collection('users').doc(newData.name);
docRef.set(newData).then(ref => {
console.log('success');
res.send('success');
}).catch(function (error) {
console.log(error);
next(error);
});
})
module.exports = router;



get

ではまず、以下の部分について説明します。公式のドキュメントを参考にしながら聞いてくれると助かります。

/* Get user list */

router.get('/', function(req, res, next) {
db.collection('users').get()
.then((snapshot) => {
var users = new Array();
snapshot.forEach((doc) => {
users.push(doc.data());
});
res.json(users);
})
.catch((err) => {
next(err);
});
});

まず、以下の部分は、expressでこのURIをgetメソッドで呼ばれた時の処理について記述をする部分を表しています。

router.get('/' ...

そのgetの中にあるdb.collection.getはfirestoreのデータを取得してくるよーということを書いています。

collection()の()に記述するのは、firestoreのどのcollectionを取得してくるかを記述しています。この場合、usersというcollectionがあらかじめfirestoreに用意しておけばその中のdocumentを操作することができるようになります。

  db.collection('users').get()

そして、最後に firestoreから取得できたデータの中から、documentのデータをすべてusersという配列に追加をしていき、最後にjson型でデータを返すという処理をやっています。もしgetに失敗した場合はfirestoreからerrorが返ってくるのでresponseとしてerrorを返すようにしています。

    .then((snapshot) => {

var users = new Array(); //からの配列を用意
snapshot.forEach((doc) => {
users.push(doc.data()); //配列に追加
});
res.json(users); // json型の配列をresponseとして返す
})
.catch((err) => {
next(err); // responseとしてerrorを返す
});


post

ここでは以下のpostの処理について説明します。

/* Post new user*/

router.post('/', function(req, res, next) {
var newData = req.body
var docRef = db.collection('users').doc(newData.name);
docRef.set(newData).then(ref => {
console.log('success');
res.send('success');
}).catch(function (error) {
console.log(error);
next(error);
});
})

まず、getの時と同じように、expressで用意されているpostのルーティングです。

router.post('/', ...

次に、リクエストのbodyにJSON型で記述されているデータをnewDataという変数に代入します。

そして、firestoreのusersというcollectionの中にnewDataのnameに入っているあたいのものがIDのdocumentをdocRefという変数で用意します。

  var newData = req.body

var docRef = db.collection('users').doc(newData.name);

最後に、新しいデータをfirestoreに追加し、その追加が成功したか、失敗したかを判定してレスポンスを返すようにします。

  docRef.set(newData).then(ref => { //指定したdocumentにnewDataを挿入

console.log('success');
res.send('success'); // successという文字をresponseとして返す
}).catch(function (error) {
console.log(error);
next(error); // エラーの場合、responseとしてerrorを返す
});


参考文献

この記事を書くにあたって、以下のリンクを参考にしました。

https://firebase.google.com/docs/reference/js/?hl=ja

https://firebase.google.com/docs/firestore/?authuser=0