質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Q&A

解決済

1回答

587閲覧

Cloud FunctionとFirestoreでプッシュ通知を送信する(firebase)

yamady

総合スコア176

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

0グッド

0クリップ

投稿2018/08/25 02:42

編集2018/08/25 08:40

いつもお世話になっております。

Cloud FunctionとFirestoreを使ってスマホ用のチャットプッシュ通知を開発しようと考えています。
元々、RealTime Databaseで動いていたものをFirestore用に書き換えているのですが、どうも最初の部分でつまずいてしまいます。。

Cloud Functionでやるとなると、だいぶ勝手が変わってしまうものなのでしょうか。

開発環境は

firebase-functions: ^0.9.1

です。

エラー内容

TypeError: snapshot.data is not a function

ソースコード

JavaScript

1// message push notification 2exports.messagePush = functions.firestore 3.document('/rooms/{roomId}/users/{uid}/messages/{messageId}') 4.onWrite((snapshot) => { 5 console.log('snapshot:', snapshot); 6 7 const item = snapshot.data(); 8 const userId = item.child("user").child("_id").val(); 9 const userName = item.child("user").child("name").val(); 10 const message = item.child("text").val(); 11 12 console.log('item', item); 13 console.log('userId', userId); 14 15 const userRef = snapshot.params.uid; 16 17 console.log('userRef', userRef); 18 19 const payload = { 20 notification: { 21 body: userName + ": " + message, 22 badge: "1", 23 sound: "default" 24 } 25 } 26 27 if (userId !== userRef) { 28 getMessageFcmToken(userRef, function(token) { 29 pushToDevice(token, payload); 30 }); 31 } 32 33 var getMessageFcmToken = function(roomId, callback) { 34 admin.firestore().collection('users').doc(`${userRef}`) 35 .then((snapshot) => { 36 console.log('Valu', snapshot.data()); 37 const token = snapshot.data()['pushToken']; 38 39 if(token == null) { 40 console.log("Nothing token"); 41 return 42 } 43 console.log("return callback token", token); 44 45 callback(token); 46 }) 47 }

コンソール結果

下記がconsole.log('snapshot:', snapshot)の結果になります。
snapshotまでは取れているみたいなのですが、なぜか、その先のsnaopshot.data()でエラーが出てしまっています。

snapshot: { data: QueryDocumentSnapshot { _ref: DocumentReference { _firestore: [Object], _referencePath: [Object] }, _fieldsProto: { _id: [Object], createdAt: [Object], text: [Object], user: [Object] }, _readTime: undefined, _createTime: Timestamp { _seconds: 1535164240, _nanoseconds: 45967000 }, _updateTime: Timestamp { _seconds: 1535164240, _nanoseconds: 45967000 } }, eventId: '2c233f09-3c86-49f8-9171-c692ea0ecb35-0', eventType: 'providers/cloud.firestore/eventTypes/document.write', notSupported: {}, params: { roomId: 'FJG4k7sBe9Pdv4ns0TW9kt01yGo2', uid: 'dtsX83vbUtMlmoFJbqcwr6fJKiS2', messageId: 'MjSGIWPJe195uIcAdKWE' }, resource: 'projects/XXXXXXXXXX/databases/(default)/documents/rooms/FJG4k7sBe9Pdv4ns0TW9kt01yGo2/users/dtsX83vbUtMlmoFJbqcwr6fJKiS2/messages/MjSGIWPJe195uIcAdKWE', timestamp: '2018-08-25T02:30:40.045967Z' }

追記(8月25日)

JavaScript

1// message push notification 2exports.messagePush = functions.firestore 3.document('/rooms/{roomId}/users/{uid}/messages/{messageId}') 4.onWrite((change, context) => { 5 6 console.log('change', change); 7 8 const document = change.after.exists ? change.after.data() : null; 9 10 console.log('document', document); 11 12 const newDocument = change.after.data(); 13 console.log('newDocument', newDocument); 14 15 // Get an object with the previous document value (for update or delete) 16 const oldDocument = change.before.data(); 17 console.log('oldDocument', oldDocument); 18 19・・・

ご回答をいただきましたようにトライしてみました。

上記のように、冒頭を書き加えてみたのですが、下記のエラーが出てしまいました。
console.log('change', change);は上と同じものを取得できましたは、exisitsが取得できず止まってしまいました。。

TypeError: Cannot read property 'exists' of undefined

続いて、existsの構文を消してやってみましたが、やはりデータのところでこけてしまいます。

TypeError: Cannot read property 'data' of undefined

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xenbeat

2018/08/25 06:12

念の為、「firebase-functions」SDKのバージョンを追記ください
yamady

2018/08/25 08:12

"firebase-functions": "^0.9.1"ですね。古いような気がしてきました・・・。
xenbeat

2018/08/25 08:14

> "firebase-functions": "^0.9.1"ですね。→ 他の人が見てもわかるように質問文に追記ください。
guest

回答1

0

ベストアンサー

使用されているonWriteは、onCreateonUpdateonDelete がトリガーされたときにトリガーされます。
その中に含まれているonUpdateは、すでに存在するドキュメントの値が変更されたときにトリガーされます。
https://firebase.google.com/docs/functions/firestore-events?hl=ja#trigger_a_function

onWriteは、ドキュメントの変更を検知するイベント(onUpdate)を含むので、変更前と変更後のデータ状態を表す2つのスナップショットがあります。
それが以下に示すafterbeforeです。

.onWrite((change) => { const newItem = change.after.data(); const oldItem = change.before.data();

追記

ご使用のSDKバージョンが<= v0.9.1(ベータ版)ということなので、かなり古いです。
特別な理由がない限り、SDKバージョンを更新してください。

npm install firebase-functions@latest --save npm install firebase-admin@5.11.0 --save // firebase-toolsのバージョンも古そうなので、ついでに更新しておきましょう。 npm install -g firebase-tools

そのままのSDKバージョンを選択せざるを得ない場合は、回答した内容では無理なので以下としてください。

.onWrite((event) => { const newItem = event.data.data(); const oldItem = event.data.previous.data();

投稿2018/08/25 04:14

編集2018/08/25 08:22
xenbeat

総合スコア4258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yamady

2018/08/25 06:00

xenbeatさま、ご回答いただきありがとうございます。changeでやってみたのですが、やはりdataのところで失敗してしまうようです。 (追記させていただきました。) なにか根本的に間違っているところがあるのでしょうか。 また、onCreateで書きなおしてもみたのですが、やはりdataが取れていない状態です。
xenbeat

2018/08/25 06:26 編集

追記依頼しました。SDKのバージョンが古いのではないかと思います。
yamady

2018/08/25 08:13

確かに、ちょこちょこlatestにするようなアラートが出ていたのでバージョンの問題であるような気がしてきました。。(汗
xenbeat

2018/08/25 08:24

やはりSDKのバージョンが古すぎますねー。解決策を回答欄に追記しました。
yamady

2018/08/25 10:18

ご丁寧な解説を頂きましてありがとうございます。バージョンについても追記が必要ですね。 現在、item.childでつまずいているのですが、おそらくfirestoreでの参照をする際にはこういう書き方をしないんですよね・・・。 取り急ぎ、最初のところが行けました。本当にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問