在文档更新中添加Firestore文档

时间:2019-04-10 16:56:00

标签: angular collections transactions google-cloud-firestore

我希望能够在一个集合中创建一个新文档,作为对另一个文档的更新的一部分。

简单版本。用户通过单击按钮来更新任务的状态。

这是我要做的

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);

或将一个连接在一起-但我希望有一个更优雅的解决方案。

2 个答案:

答案 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中的更改的用户(我相信您可以实时)。

相关问题