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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

Q&A

解決済

1回答

807閲覧

FireStoreでコレクション全体に対してupdate処理が走らないです

dialbird

総合スコア379

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

0グッド

0クリップ

投稿2020/03/29 12:31

編集2020/03/30 11:54

Firebase(もといNoSQL系)に関しては初心者なものです!

Firestoreのテーブルをまたいで、複数のドキュメントに対して、forEachで更新をかけたいのですが、処理の負荷(?)の影響なのか、関数を走らせた後も一向にDBが更新される様子が見られないのです

js

1const firestore = admin.firestore(); 2 3firestore.collection("users").get().then(snap => { 4 snap.forEach(doc => { 5 const user = doc.data(); 6 firestore.collection("rooms").doc(user.roomId).update({timezone: user.timezone}) 7 }) 8})

この処理自体はCloudFunctionでダミーの関数をアップして、それを手動で直接呼び出している感じです(あまりいい方法ではないかもですが)

その方法で実行すると、limitなどで、usersコレクションのうちの少数にだけ更新処理を実施する場合にはうまく行くのですが、コレクション全体(700件くらい)に対して一気にforEachでやろうとすると、どうしたわけかいつまでたってもDBが更新されないのです。

何かエラーログが吐かれているわけでもないようです。
大量のデータ更新はできないものなのでしょうか?

その場合、どのようにしたらうまく行くのでしょうか?
よろしくお願いいたします

追記:

以下のように書き換えてみたところ、原因はタイムアウトエラーによるものであることが判明しました

js

1firestore.collection("users").get().then(snap => { 2 let promises = []; 3 snap.forEach(doc => { 4 const user = doc.data(); 5 promises.push(firestore.collection("rooms").doc(user.roomId).update({timezone: user.timezone})); 6 }) 7 return Promise.all(promises) 8}).catch(err => { 9 console.log(`err: ${err}`); 10 // err: Error: Retry total timeout exceeded before any response was received 11})

おそらくは実行元がクラウドファンクションであることも一因であるかもとは思うのですが、タイムアウトエラーを起こさずに、700件近くのドキュメントを同時に更新するにはどのような手法があるのでしょうか?

そういったクエリを管理者的に、権限を無視してFirestoreに送りつけられる方法がありましたら教えて欲しいです!

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

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

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

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

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

guest

回答1

0

自己解決

HTMLファイルにスクリプトだけ書いて読み込ませることで実行できました!

要するに今回の問題は
「スクリプトとしてはあっていたけど、クラウドファンクションで実行したがために、タイムアウトエラーが起こっていた」
ということになりましょう

ただ現状の問題としては、実行する瞬間だけ、DBのwriteルールを無条件にtrueにする必要があることです

ブラウザからでも何か「管理者権限」みたいなものを付与できる仕組みがあれば良いのですが、とりあえず解決はしたのでこの質問はクローズします

html

1<body> 2 <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-app.js"></script> 3 <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-firestore.js"></script> 4 <script> 5 const config = { 6 apiKey: "apikey", 7 authDomain: "domain", 8 databaseURL: "url", 9 projectId: 'id' 10 }; 11 firebase.initializeApp(config); 12 const db = firebase.firestore(); 13 db.collection("users").get().then(snap=>{ 14 let promises = []; 15 snap.forEach(doc=> { 16 const user = doc.data(); 17 promises.push(db.collection("rooms").doc(user.uid).update({timezone: user.timezone})); 18 }) 19 return Promise.all(promises) 20 }).then(hoge => { 21 console.log('終わったよ'); 22 }).catch(err => { 23 console.log(`err: ${err}`); 24 }) 25 </script> 26</body>

投稿2020/03/30 22:51

dialbird

総合スコア379

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

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

dialbird

2020/03/30 23:11

hoshi-takanoriさん 早速ありがとうございます! なるほど つまり - 先に管理者役のユーザーをAuthenticationで作っておいて - それに管理者権限を付与して - ブラウザで実行する際には毎回その管理者としてログインしてから処理を実施するようにする という感じなのでしょうか? ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問