我希望能够在一个集合中创建一个新文档,作为对另一个文档的更新的一部分。
简单版本。用户通过单击按钮来更新任务的状态。
这是我要做的
completeTask(task:ITask) : Promise<any>
{
const userId = this.auth.userId;
this.afs.collection('Tasks').doc(task.id).update({Status: 'COMPLETE'});
this.afs.collection('Notifications').add({Task:task.id, Status: 'COMPLETE', UserId: userId});
// ...
// return Promise here;
}
以上操作需要作为单个操作的一部分进行。 我已经阅读了有关批处理和事务的所有内容,但似乎找不到正确的方法。 我可以按顺序运行它们并返回一个
Promise.all(taskPromise, notifyPromise);
或将一个连接在一起-但我希望有一个更优雅的解决方案。
答案 0 :(得分:0)
如果您希望两次写操作作为一项操作发生(要么都成功,要么都没有发生),则应use a batched write or transaction。承诺是一种客户端机制,因此不是实现原子性的理想方法。
答案 1 :(得分:0)
我找到了想要的答案。 将文档作为批处理的一部分存在的问题是,您必须生成自己的密钥-使用管理的密钥或从Firestore获取密钥。在事后看来,这很明显,因为该批处理需要处理给定的文档-我对正常引用中的.add()会添加新文档并为其指定一个ID的事实感到分心-我正在寻找一种方法来批量执行此操作。
这是我最终使用的代码
@Injectable({
providedIn: 'root'
})
export class ProjectService {
// AuthService is implied but not shown as part of this example
constructor(private afs: AngularFirestore, private auth:AuthService) { }
// Update Project and write an event log to the projects ActivityLog
// as part of the same write
UpdateProject(projectName: string, data:any) : Promise<void>
{
// Get a batch reference
const batch = this.afs.firestore.batch();
// Reference to the Project document that needs to be updated
const ref = this.afs.collection('Projects').doc(projectName);
// Get a unique Firestore ID for the ActivityLog document
const newLogId = this.afs.createId();
// Reference to the ActivityLog doc using the ref and ID created above
const logref = ref.collection('ActivityLog').doc(newLogId);
batch.update(ref.ref, data);
// Create the new entry
batch.set(logref.ref, {
Created: firestore.FieldValue.serverTimestamp(),
User: this.auth.UserName,
Action: 'Update',
Data: JSON.stringify(data)
});
return batch.commit();
}
}
在我的组件中
onUpdate(data:any) {
this.projectSvc.UpdateProject(this.projectName, data)
.then(() => alert('Update successful'));
}
关键位是生成ID,并在引用新的ActivityLog(在这种情况下)文档时使用它。
侧边栏:可能已经作为Cloud Function完成了-我们甚至正在查看的原因是,我们需要了解做出更改的用户,并且根据研究结果,您无法获得该ID。触发了Firestore中的更改的用户(我相信您可以实时)。