Help us understand the problem. What is going on with this article?

[Firestore]チュートリアルを試してみた(Node編)

概要

  • Firebase公式サイトにあるCloud Firestore データベースを作成するを試してみた記録です
  • NodeからFirestoreへの書き込み/読み取りを実装してみます
  • Firestoreを操作する処理をExpressを使ってAPIとして公開するところまで紹介します

Firestoreのデータベースを作成する

  • Firebaseのコンソールで操作していきます
  • ログインしたら「プロジェクトを追加」からプロジェクトを作成します
    スクリーンショット 2019-09-19 23.18.59.png
    スクリーンショット 2019-09-19 23.21.32.png
    スクリーンショット 2019-09-19 23.22.11.png

  • プロジェクトの作成には少し時間がかかります

  • 作成できたらサイドメニューの「データベース」を選択し「データベースを作成」から作成していきます
    スクリーンショット 2019-09-19 23.23.12.png

  • NodeでFirestoreにアクセスする場合はテストモードとロックモードどちらでも大丈夫です

  • Webからはテストモードでないとアクセスできないので検証の用途で使いまわしたい場合はテストモードにしておいてもいいかも

スクリーンショット 2019-09-19 23.26.09.png

  • 作成が完了したら準備OKです スクリーンショット 2019-09-19 23.29.45.png

サービスアカウントの秘密鍵の取得

  • Firestoreにアクセスするための秘密鍵を取得しておきます
    • 歯車から「プロジェクトの設定」->「サービスアカウント」->「新しい秘密鍵の生成」
    • ファイル名は何でもいいですがここではServiceAccount.jsonで保存しておきます スクリーンショット 2019-09-19 23.37.52.png

NodeからFirestoreにアクセスする

  • 適当なディレクトリを作成しセットアップ
mkdir firestore-sample-node
cd firestore-sample-node
npm init -y
  • Firebase関連のSDKをインストールする
npm i firebase-admin firebase-functions
  • jsファイルの作成
    • index.jsを作成し以下の内容を記述
    • この例ではServiceAccount.jsonをfirestore-sample-nodeフォルダ直下においている
index.js
const admin = require('firebase-admin');
const functions = require('firebase-functions');
const ServiceAccount = require('./ServiceAccount.json');

admin.initializeApp({ credential: admin.credential.cert(ServiceAccount) });

const db = admin.firestore();
const docRef = db.collection('users').doc('alovelace');

const setAda = docRef.set({
  first: 'Ada',
  last: 'Lovelace',
  born: 1815,
});
  • 実行してみる
node index.js
  • Firestoreのコンソールを見てみるとデータが追加されています
    スクリーンショット 2019-09-19 23.51.43.png

  • ※RDBの感覚で言うとCollectionはテーブル、Documentはレコード

  • 更にデータを追加してみる

index.js
const admin = require('firebase-admin');
const functions = require('firebase-functions');
const ServiceAccount = require('./ServiceAccount.json');

admin.initializeApp({ credential: admin.credential.cert(ServiceAccount) });

const db = admin.firestore();
const docRef = db.collection('users').doc('alovelace');

const setAda = docRef.set({
  first: 'Ada',
  last: 'Lovelace',
  born: 1815,
});

const aTuringRef = db.collection('users').doc('aturing');

const setAlan = aTuringRef.set({
  first: 'Alan',
  middle: 'Mathison',
  last: 'Turing',
  born: 1912,
});
  • 実行する
node index.js

スクリーンショット 2019-09-19 23.56.18.png

  • 次は登録したデータを取得してみる
index.js
const admin = require('firebase-admin');
const functions = require('firebase-functions');
const ServiceAccount = require('./ServiceAccount.json');

admin.initializeApp({ credential: admin.credential.cert(ServiceAccount) });

const db = admin.firestore();
const docRef = db.collection('users').doc('alovelace');

db.collection('users')
  .get()
  .then(snapshot => {
    snapshot.forEach(doc => {
      console.log(doc.id, '=>', doc.data());
    });
  })
  .catch(err => {
    console.log('Error getting documents', err);
  });
  • 実行する
node index.js

スクリーンショット 2019-09-19 23.59.19.png

  • ここまでで基本的なデータの登録/取得は完了です

ExpressでAPIとして公開する

  • これまではスクリプトを実行して処理を動かしていました
  • Expressを使ってHTTPでのアクセスによってFirestoreへの登録/取得ができるようにしてみます
  • 新しく作業用のフォルダを作成しセットアップ
mkdir firestore-sample-express
cd firestore-sample-express
npm init -y
npm i express body-parser firebase-admin firebase-functions
  • index.jsを作成する
    • ServiceAccount.jsonはさっきのものを使い回す
    • まずはHelloを返すエンドポイントだけ作成
index.js
const express = require('express');
const bodyParser = require('body-parser');
const admin = require('firebase-admin');
const functions = require('firebase-functions');
const ServiceAccount = require('./ServiceAccount.json');

// Firebaseのinitialize
admin.initializeApp({ credential: admin.credential.cert(ServiceAccount) });

// Firestoreの参照を取得
const db = admin.firestore();
const docRef = db.collection('messages');

// Expressのセットアップ
const app = express();
app.use(bodyParser.json());

// GETで/helloにアクセスするとこの関数が実行される
app.get('/hello', (req, res) => {
  res.send('Hello');
});

// Expressを起動する
const port = '8080';
app.listen(port, () => console.log(`app start listening on port ${port}`));
  • アプリを起動する
node index.js
  • /helloにアクセスして動作確認
curl -X GET localhost:8080/hello
Hello
  • messagesコレクションにデータを登録/取得するエンドポイントを追加する
index.js
// 省略

app.get('/messages', async (req, res) => {
  // messagesコレクションのデータを全量取得
  const snapshots = await docRef.get();
  // レスポンスからデータ部分のみ取り出す
  const messages = snapshots.docs.map(doc => doc.data());
  res.send(messages);
});

app.post('/messages', async (req, res) => {
  const message = {
    text: req.body.text,
    timestamp: admin.firestore.FieldValue.serverTimestamp(), // このように書くとtimestampも保存できる
  };
  await docRef.add(message);
  res.send(message);
});

// 省略
  • アプリを再起動
node index.js
  • メッセージを登録してみる
curl -X POST -H "Content-Type: application/json" -d '{"text": "こんにちは"}' localhost:8080/messages

スクリーンショット 2019-09-20 0.35.38.png

  • メッセージを取得してみる
curl -X GET localhost:8080/messages

スクリーンショット 2019-09-20 0.37.44.png

  • これらのAPIを叩くことでWebアプリやスマホアプリからFirestoreへのデータ登録/取得ができちゃいます!
  • Expressで作ったアプリをAWS Lambdaで動かすまでで紹介している手順と組み合わせればAPIをLambdaに公開することも簡単にできてしまいます!
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away