firebase firestore 在事务中添加新文档-transaction.add 不是函数
Posted
技术标签:
【中文标题】firebase firestore 在事务中添加新文档-transaction.add 不是函数【英文标题】:firebase firestore adding new document inside a transaction - transaction.add is not a function 【发布时间】:2019-09-04 13:02:50 【问题描述】:我假设可以执行以下操作:
transaction.add(collectionRef,
uid: userId,
name: name,
fsTimestamp: firebase.firestore.Timestamp.now(),
);
但显然不是:
transaction.add 不是函数
以上消息显示在 chrome 控制台内。
我看到我们可以使用事务的set方法来事务性地添加一个新文档。见:https://firebase.google.com/docs/firestore/manage-data/transactions
问题是如果我使用 set 而不是 add(无论如何都不支持),文档的 id 应该由我手动创建,firestore 不会创建它。 见:https://firebase.google.com/docs/firestore/manage-data/add-data
如果没有自动为您生成 id 的 add 方法,您是否发现这样做的任何缺点?
例如,考虑到包括性能在内的各种问题,firestore 本身生成的 id 是否可能以某种方式进行了优化?
在使用 transaction.set 时,您使用哪个库/方法在 react-native 中创建文档 ID?
谢谢
【问题讨论】:
【参考方案1】:如果您想生成一个唯一 ID 以供以后在事务中创建文档时使用,您所要做的就是使用不带参数的 CollectionReference.doc() 来生成一个 DocumentReference,您可以稍后在事务中设置()。
(您在回答中提出的建议是为了达到同样的效果需要做更多的工作。)
// Create a reference to a document that doesn't exist yet, it has a random id
const newDocRef = db.collection('coll').doc();
// Then, later in a transaction:
transaction.set(newDocRef, ... );
【讨论】:
db.collectionRef
你的意思是db.collection
,对吧?
@DougStevenson 嗯,当我尝试这个时,我遇到了一个错误:FirebaseError: Function CollectionReference.doc() 要求它的第一个参数是非空字符串类型,但它是:未定义。有更新吗?
好的,我可以看到,它不适用于 angularfire:/
@DougStevenson:这是否意味着文档 ID 被保留?如果是这样:是否需要在事务中调用 doc()?或者我们是否依赖 id 生成器在另一个不相关的调用中不统计地提供这个值?【参考方案2】:
经过更多挖掘后,我在 firestore 本身的源代码中发现了以下用于 id 生成的类/方法:
export class AutoId
static newId(): string
// Alphanumeric characters
const chars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let autoId = '';
for (let i = 0; i < 20; i++)
autoId += chars.charAt(Math.floor(Math.random() * chars.length));
assert(autoId.length === 20, 'Invalid auto ID: ' + autoId);
return autoId;
见:https://github.com/firebase/firebase-js-sdk/blob/73a586c92afe3f39a844b2be86086fddb6877bb7/packages/firestore/src/util/misc.ts#L36
我提取了方法(除了 assert 语句)并将其放在我的代码中的方法中。然后我使用了事务的set方法如下:
generateFirestoreId()
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let autoId = '';
for (let i = 0; i < 20; i++)
autoId += chars.charAt(Math.floor(Math.random() * chars.length));
//assert(autoId.length === 20, 'Invalid auto ID: ' + autoId);
return autoId;
那么,
newDocRef = db.collection("PARENTCOLL").doc(PARENTDOCID).collection('SUBCOLL').doc(this.generateFirestoreId());
transaction.set(newDocRef,
uid: userId,
name: name,
fsTimestamp: firebase.firestore.Timestamp.now(),
);
由于我使用与 firestore 本身相同的 id 生成算法,我感觉更好。
希望这可以帮助/指导某人。
干杯。
【讨论】:
【参考方案3】:根据 Doug Stevenson 的回答,这就是我使用 @angular/fire 的方式:
// Create a reference to a document and provide it a random id, e.g. by using uuidv4
const newDocRef = this.db.collection('coll').doc(uuidv4()).ref;
// In the transaction:
transaction.set(newDocRef, ... );
【讨论】:
【参考方案4】:完成 Stefan 的回答。对于那些使用 Angularfire 的用户,在 5.2 版之前使用 CollectionReference.doc() 会导致错误“CollectionReference.doc() 要求其第一个参数是非空字符串类型”。
这个解决方法对我有用:
const id = this.afs.createId();
const ref = this.afs.collection(this.collectionRef).doc(id);
transaction.set(ref, ... );
信用:https://github.com/angular/angularfire/issues/1974#issuecomment-448449448
【讨论】:
【参考方案5】:我想添加一个解决id
问题的答案。无需生成您自己的id
s。 documentReference
在调用 transaction.set()
后更新,因此要访问 Firestore 的 id
,您只需执行以下操作:
const docRef = collectionRef.doc();
const result = await transaction.set(docRef, input);
const id = docRef.id;
【讨论】:
以上是关于firebase firestore 在事务中添加新文档-transaction.add 不是函数的主要内容,如果未能解决你的问题,请参考以下文章
Firestore是否提供更多的锁定事务,比如表到表的概念?
Flutter Firebase/Firestore 一次写入多个表
在 pubspec.yaml 文件中添加 firebase_auth 或 cloud_firestore 时构建失败并出现异常(firebase_core 正在工作):
如何在不覆盖的情况下向 Firebase Firestore 添加值?