やること
Firestore へのデータの書き込み、データの読み込みの方法を思い出すための、最小限のコードと手順をメモしたものです。
参考
この二つを読めば十分できるんですが、上の記事を読んで「あーなるほど」と思えるレベルまで辿り着く前に、挫折してしまった場合のためのメモです。
準備
最小限必要なもの
- Google アカウント
- Firebase を使えるようにしておく: 参考 Firebase で hello world と表示するページを作る方法: プロジェクトの作成までできればOK
- 適当なブラウザ (Chrome, Edge など)
Firebase 側で必要な準備
最低限、プロジェクトひとつの作成と、アプリケーションひとつの作成が必要です。
プロジェクトを作成するには、ブラウザで Firebase コンソールに行きます。
コンソールの左上あたるは、上のような表示になっているはずです(絵は違うかもしれない)。ここで「プロジェクトを追加」を押します。
プロジェクト名を入れるように言われるので、何か入れます。URLとして使える文字列になってる必要があります(多分)。また、他のプロジェクト名と重複していない必要もあるので、長い目の文字列にしておいたほうが良いです(多分)。
入力したら「続行」を押します。
次に Google Analytics の機能をONにするか聞かれます。今回は、プロジェクトをテストに使うだけなので、オフにしておきます。(オンにするとこの次のページでいろいろ設定を聞かれます)
「プロジェクトを作成」を押すとこんな画面になるので、待ちます。
こうなった「続行」を押します。
アプリケーションの作成
Firestore に Web ページ内からアクセスするあtめには、最低限ひとつの Web アプリケーションを作っておく必要があります。
プロジェクトを作成したら、下のような画面になります(絵は違うかもしれない)。
中央の左に</>
みたいなアイコンがあって、そこを押すと Web アプリケーションを作成できます。そのアイコンを押します。
アプリ名を入れます。Hosting については、今回はローカルでしかテストしないので、使用しないことにします。
これで「作成」を押すと、しばらくしてから次のような画面になります。
上の画面でグレーになっている部分は、javascript で firestore にアクセスするために必要なコードなので、この部分をエディタなどにコピーしておきます。apiKey のところを黒塗りにしてますが、ここにも文字列が入っているはずです。
apiKey などの情報の再表示
apiKey の情報のコピペを忘れてしまった場合は、下記の手順で再度表示させることができます。
まずプロジェクトの画面に行きます。画面の左上あたり「プロジェクトの概要」という項目があります。その右に歯車マークがあるので、それを押します。
歯車を押して出るメニューから「プロジェクトを設定」を選びます。
プロジェクト内にあるアプリの一覧が表示されているので、apiKey などの情報が欲しいアプリを探します。「SDKの設定と構成」のところで「CDN」を選ぶと、プロジェクト作成時と同じように javascript のコードが表示されるので、これをコピーします。
apiKey 公開は大丈夫なのか?
下記がとても参考になります。
基本的には大丈夫のようですが、後述する firestore 側のルールがテストモードで無制限アクセス可能になっていたりすると、データベースを荒らされたり、無限に課金させられる可能性がありそうです。
後悔公開する前に、セキュリティルール(後述)は見直しておきましょう。
firestore でデータベースを作成する
プロジェクトの画面の左のメニューにある Firestore Database のメニューを選びます。すると、下のような画面になります。
この画面で「データベースの作成」を押します。
セキュリティルールを選択する画面が出るので、ここでは「テストモードで開始する」を押します。
apiKey のところでも書いてますが、この部分は実はかなり重要です。アプリを deploy してテストする場合、apiKey などの情報が公開された状態になるので、テストモードのまま公開すると第三者にデータベースを荒らされる可能性があります。
ローカルでだけテストする場合でも、何かの拍子(たとえば github の public なレポジトリに push したとか)に apiKey などの情報が流出する可能性もあるので、最低限アクセスできる期限くらいは設けたほうが良さそうです(多分)。
詳しくは下記を参照のこと。
次にロケーションを選択する画面になります。テストするだけならどこを選んでも良いです。gcp でどこかのロケーションを選択していて、何らか連携する必要がある場合は、それにあわせてロケーションを選びます(異なるロケーション間の通信は料金がかることがあります)。
ロケーションを押して「有効にする」を押すと、プロビジョニングが始まります。
プロビジョニングが終了すると、下のような画面になります。
この状態になれば、さきほどコピペした apiKey などの情報を使って、Firestore Database に読み書きできるようになります。
ちなみに、コマンドラインから firebase コマンドを使って firestore databse を作成することもできます。
$ firebase init firestore
firestore を使う
最小限に近いコード(多分)
下記をコピペして firestore.html などの名前で作成します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>firestore test</title>
</head>
<body>
<div id="store_sample">
<input id="words" type="text" value=""/>
<input type="button" value="送信" onclick="send();"/>
<input type="button" value="受信" onclick="recieve();"/>
<br/>
<div id="output">
</div>
</div>
<script src="https://www.gstatic.com/firebasejs/8.8.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.8.0/firebase-firestore.js"></script>
<script>
let db;
let mode = true;
function init(){
// 以下、控えておいた情報に書き換える
let firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxx.firebaseapp.com",
projectId: "xxxxxxxxxx",
storageBucket: "xxxxxxxxxx.appspot.com",
messagingSenderId: "xxxxxxxxxx",
appId: "xxxxxxxxxx"
};
firebase.initializeApp(firebaseConfig); // firestore 初期化
db = firebase.firestore(); // db 初期化
}
function send()
{
let word = document.getElementById('words').value;
console.log( word );
let sample = db.collection("sample"); // コレクション sample
if ( mode == true ){
// set はドキュメントの名前を指定して追加する
// すでに同のドキュメントがあると上書きする
sample.doc(word).set({
time: firebase.firestore.FieldValue.serverTimestamp()
});
}else{
// set はドキュメントの名前を指定しないで追加する
// 仕組み的に上書きされることはない。
sample.add({
data: word,
time: firebase.firestore.FieldValue.serverTimestamp()
}).then(function(e) {
console.log("success", e);
}).catch(function(e) {
console.error("error", e);
});
}
}
function recieve()
{
let output = document.getElementById('output');
let sample = db.collection("sample"); // コレクション sample
// 全部のデータを取得する。
sample.get().then(e => {
let arr = [];
e.forEach(d => {
let dat = d.data();
console.log( dat );
if ( dat.time != null ){
let t = dat.time.toDate();
arr.push(t);
}
});
output.innerText = arr.join(':');
});
}
init();
</script>
</body>
</html>
実行
上記ファイルを chrome とか Edge とか Firefox などのブラウザで開くと、下記のような画面になります(多分)。
この状態で、テキストフィールドに test と入れて「送信」とします。
すると、Firestore のデータベースの画面の中に sample というコレクションが追加されて、その中に test というドキュメントが追加され、データとしてタイムスタンプが登録されるはずです。
こうなります。ならない場合は、コードが間違っているか、apiKey などの情報が間違っているか、開いてる Firestore のプロジェクトが間違っているか、セキュリティルールが期限切れなどになっていてアクセスできないか、そのへんのどれかです(多分)。ブラウザのコンソールに、何らかのエラーが出ている可能性があるので、確認します。
このくらいデータを追加したのちに「受信」を押すと、追加されているデータのタイムスタンプ一覧が表示されます。
ここまでできたら、もうできたも同然!
あとは下記を読めば何とかなるはずです(きっと)。
コード中にある mode = true
を mode = false
にすると、ドキュメント名をランダムかつユニークな文字列にして、入力したテキストはデータとして追加するようになります。
おわり
firestore にタイムスタンプのデータを入れたい時に、単に Date.now()
ではだめで、firebase.firestore.FieldValue.serverTimestamp()
としないといけないようです、逆(デコード?)は timestamp.toDate()
です。(コード参照のこと)