如何使用 Firebase 管理员更新 FireStore 中包含数千个文档的集合中的所有文档?
已更新以反映 Firebase-Admin,而不是 v9 新更新:底部的解决方案
如何在 firebase-admin/firestore (10.0.2) 中更新包含数千个文档的集合中的所有文档的单个字段(在地图中)?我尝试使用它:
import { getFirestore } from 'firebase-admin/firestore'
const db = getFirestore()
db.collection("users").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
doc.ref.update({
"words.subscription": 0
})
})
})
我在 Node.js (v12) 云函数中使用它。该函数运行,我没有看到任何错误,但没有任何文档被更新。以前,我尝试使用 set()
因为某些文档可能没有该字段,但 Frank 让我知道 update()
也可以更新不存在的字段。
但是,此更新的代码也不会更新“users”集合中的所有文档。
先感谢您。
更新/解决方案 @Dharmara - 谢谢你的要点。它不能按原样工作,所以我决定更改为 async/await 并将其包装在 try/catch 中(希望找出它不起作用的原因),如下所示:
try {
let querySnapshot = await db.collection('users').get()
if (querySnapshot.size === 0) {
console.log('No documents to update')
return 'No documents to update'
}
const batches: any[] = [] // hold batches to update at once
querySnapshot.docs.forEach((doc, i) => {
if (i % 500 === 0) {
batches.push(db.batch())
}
const batch = batches[batches.length - 1]
batch.update(doc.ref, { "words.subscription": 0 })
})
await Promise.all(batches.map(batch => batch.commit()))
console.log(`${querySnapshot.size} documents updated`)
return `${querySnapshot.size} documents updated`
}
catch (error) {
console.log(`***ERROR: ${error}`)
return error
}
然而,当我测试它时,它起作用了。据我所知,它与您在要点中使用的 then()
方式相同(以及我在 SO 的其他地方找到的内容)。
如果您想将其放入答案中,我很乐意将其标记为答案。你的代码帮了很大的忙。谢谢。
Updated to reflect Firebase-Admin, rather than v9
New Update: solution at the bottom
How to update a single field (in a map) for all documents in a collection with thousands of documents -- in firebase-admin/firestore (10.0.2)? I attempted to use this:
import { getFirestore } from 'firebase-admin/firestore'
const db = getFirestore()
db.collection("users").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
doc.ref.update({
"words.subscription": 0
})
})
})
I use it within a Node.js (v12) cloud function. The function runs, I see no errors, but none of the documents are updated. Previously, I attempted to use set()
because some documents may not have the field, but Frank let me know update()
can update fields that don't exist too.
However, this updated code also does not update all the documents in the 'users' collection.
Thank you in advance.
Update/Solution
@Dharmara - thank you for the gist. It did not work as-is, so I decided to change to async/await and wrap it in try/catch (to hopefully find out why it wasn't working), like so:
try {
let querySnapshot = await db.collection('users').get()
if (querySnapshot.size === 0) {
console.log('No documents to update')
return 'No documents to update'
}
const batches: any[] = [] // hold batches to update at once
querySnapshot.docs.forEach((doc, i) => {
if (i % 500 === 0) {
batches.push(db.batch())
}
const batch = batches[batches.length - 1]
batch.update(doc.ref, { "words.subscription": 0 })
})
await Promise.all(batches.map(batch => batch.commit()))
console.log(`${querySnapshot.size} documents updated`)
return `${querySnapshot.size} documents updated`
}
catch (error) {
console.log(`***ERROR: ${error}`)
return error
}
When I tested this however, it worked. From what I can tell it's the same as the then()
way you had in the gist (and from what I had found elsewhere in SO).
If you wanted to put this into an answer I'd gladly mark it as the answer. Your code helped tremendously. Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
用于编写嵌套字段的点表示法仅在调用
update()
时有效,不适用于set()
。幸运的是update()
适用于不存在的字段,它只要求文档已经存在。因此,对于 v8 及之前的命名空间 API 来说:
对于 v9 及更高版本的模块化 API,它是:
The dot notation you use to write a nested field only works when you call
update()
, not forset()
. Luckilyupdate()
works for non-existing fields, it only requires that the document already exists.So for the namespaced API of v8 and before that'd be:
For the modular API for v9 and beyond, it's: