Node.js Firestore事务在单个事务中更新多个集合

Node.js Firestore事务在单个事务中更新多个集合,node.js,firebase,google-cloud-firestore,google-cloud-functions,Node.js,Firebase,Google Cloud Firestore,Google Cloud Functions,如何使用我搜索过但没有得到任何答案的单个事务更新firestore中的多个集合。是否可以在一个事务中更新多个集合 我想在教室和学生集合中立即更新分支。名称 正如Node.js客户端库方法的文档中所解释的,它返回一个“用于链接方法调用”(请注意,Admin SDK的方法的行为方式完全相同) 因此,例如,如果在事务中您希望从课堂文档中获取一个值,增加它并使用它更新来自两个不同集合的两个文档(课堂和学生),您将执行以下操作: const db = firebase.firestore(); //o

如何使用我搜索过但没有得到任何答案的单个事务更新firestore中的多个集合。是否可以在一个事务中更新多个集合

我想在教室和学生集合中立即更新分支。名称


正如Node.js客户端库方法的文档中所解释的,它返回一个“用于链接方法调用”(请注意,Admin SDK的方法的行为方式完全相同)

因此,例如,如果在事务中您希望从课堂文档中获取一个值,增加它并使用它更新来自两个不同集合的两个文档(
课堂
学生
),您将执行以下操作:

const db = firebase.firestore();  //or admin.firestore() in a Cloud Function
const docRef1 = db.collection('classrooms').doc('classroomDocId');
const docRef2 = db.collection('students').doc('studentDocId');


let transaction = db.runTransaction(t => {
  let newNumericValue;
  return t.get(docRef1 )
    .then(doc => {
      newNumericValue = doc.data().numericValue + 1;  //You calculate the new value
      return t.update(docRef1 , {numericValue : newNumericValue});
    }).then(t => {
      return t.update(docRef2 , {numericValue : newNumericValue});
    });
}).then(result => {
  console.log('Transaction success!' + result);
}).catch(err => {
  console.log('Transaction failure:', err);
});
let batch = db.batch();

let cRef = db.collection('classrooms').doc('classroomDocId');
batch.set(cRef, {branch.name: 'newName'});

let sRef = db.collection('students').doc('studentDocId');
batch.update(sRef, {branch.name: 'newName'});

return batch.commit().then(function () {
  // ...
});

请注意,如果需要在多次更新之前执行多次读取,“在使用事务时,读取操作必须在写入操作之前进行。”


另一方面,如果您只想更新多个文档,而不阅读
一个或多个值(您在问题中说“希望在课堂和学生集合中立即更新branch.name”),则不需要使用事务。只需使用一个,如下所示:

const db = firebase.firestore();  //or admin.firestore() in a Cloud Function
const docRef1 = db.collection('classrooms').doc('classroomDocId');
const docRef2 = db.collection('students').doc('studentDocId');


let transaction = db.runTransaction(t => {
  let newNumericValue;
  return t.get(docRef1 )
    .then(doc => {
      newNumericValue = doc.data().numericValue + 1;  //You calculate the new value
      return t.update(docRef1 , {numericValue : newNumericValue});
    }).then(t => {
      return t.update(docRef2 , {numericValue : newNumericValue});
    });
}).then(result => {
  console.log('Transaction success!' + result);
}).catch(err => {
  console.log('Transaction failure:', err);
});
let batch = db.batch();

let cRef = db.collection('classrooms').doc('classroomDocId');
batch.set(cRef, {branch.name: 'newName'});

let sRef = db.collection('students').doc('studentDocId');
batch.update(sRef, {branch.name: 'newName'});

return batch.commit().then(function () {
  // ...
});

根据您的评论进行更新

在云函数中,您可以很好地链接不同的Firestore查询(使用
where()
),并在每个
then()
中填充批,然后在最后一个
then()
中提交批。请参见下面的示例(仅使用正确的查询进行调整):


正如Node.js客户端库方法的文档中所解释的,它返回一个“用于链接方法调用”(请注意,Admin SDK的方法的行为方式完全相同)

因此,例如,如果在事务中您希望从课堂文档中获取一个值,增加它并使用它更新来自两个不同集合的两个文档(
课堂
学生
),您将执行以下操作:

const db = firebase.firestore();  //or admin.firestore() in a Cloud Function
const docRef1 = db.collection('classrooms').doc('classroomDocId');
const docRef2 = db.collection('students').doc('studentDocId');


let transaction = db.runTransaction(t => {
  let newNumericValue;
  return t.get(docRef1 )
    .then(doc => {
      newNumericValue = doc.data().numericValue + 1;  //You calculate the new value
      return t.update(docRef1 , {numericValue : newNumericValue});
    }).then(t => {
      return t.update(docRef2 , {numericValue : newNumericValue});
    });
}).then(result => {
  console.log('Transaction success!' + result);
}).catch(err => {
  console.log('Transaction failure:', err);
});
let batch = db.batch();

let cRef = db.collection('classrooms').doc('classroomDocId');
batch.set(cRef, {branch.name: 'newName'});

let sRef = db.collection('students').doc('studentDocId');
batch.update(sRef, {branch.name: 'newName'});

return batch.commit().then(function () {
  // ...
});

请注意,如果需要在多次更新之前执行多次读取,“在使用事务时,读取操作必须在写入操作之前进行。”


另一方面,如果您只想更新多个文档,而不阅读
一个或多个值(您在问题中说“希望在课堂和学生集合中立即更新branch.name”),则不需要使用事务。只需使用一个,如下所示:

const db = firebase.firestore();  //or admin.firestore() in a Cloud Function
const docRef1 = db.collection('classrooms').doc('classroomDocId');
const docRef2 = db.collection('students').doc('studentDocId');


let transaction = db.runTransaction(t => {
  let newNumericValue;
  return t.get(docRef1 )
    .then(doc => {
      newNumericValue = doc.data().numericValue + 1;  //You calculate the new value
      return t.update(docRef1 , {numericValue : newNumericValue});
    }).then(t => {
      return t.update(docRef2 , {numericValue : newNumericValue});
    });
}).then(result => {
  console.log('Transaction success!' + result);
}).catch(err => {
  console.log('Transaction failure:', err);
});
let batch = db.batch();

let cRef = db.collection('classrooms').doc('classroomDocId');
batch.set(cRef, {branch.name: 'newName'});

let sRef = db.collection('students').doc('studentDocId');
batch.update(sRef, {branch.name: 'newName'});

return batch.commit().then(function () {
  // ...
});

根据您的评论进行更新

在云函数中,您可以很好地链接不同的Firestore查询(使用
where()
),并在每个
then()
中填充批,然后在最后一个
then()
中提交批。请参见下面的示例(仅使用正确的查询进行调整):


我不明白,教室和学生之间的关系是什么,分支是什么,如果它有Id,为什么不把它移到新的集合中?事务不允许你修改集合中的所有文档。您必须标识要更改的每个文档,并在事务处理程序中分别使用它们。您可以通过这种方式修改多个集合中的文档。我不明白,教室和学生之间的关系是什么,分支是什么,如果它有Id,为什么不将其移出并添加到新集合?事务不允许您修改集合中的所有文档。您必须标识要更改的每个文档,并在事务处理程序中分别使用它们。您可以通过这种方式修改多个集合中的文档。感谢您的帮助,这是我的批更新代码
let batch=admin.firestore().batch();admin.firestore().collection('students').where('branch.id','==',documentId.).get().then((querySnapshot)=>{querySnapshot.forEach((doc)=>{batch.update(doc.ref,{branch:{id:documentId,name:after.name}});});return batch.commit();}.catch(err=>{console.log('error==>',err);})
但我的问题是如何使用where子句ex:
let student_public=admin.firestore().collection('student_public')。where('branch.id','==',documentId);
let questions=admin.firestore().collection('questions')。where('branch.id','=',documentId);
我知道你的代码是云函数代码。你应该注意返回
get()
返回的承诺(请参阅Firebase视频系列中关于“JavaScript承诺”的3个视频:解释了这一关键点)。你可以很好地链接不同的Firestore查询(带where)在每个then()中填充批处理,然后在最后一个中提交批处理。承诺我已经用一个示例更新了答案。如果您认为我的答案为您提供了问题的解决方案,请接受并投票,请参阅。谢谢!感谢帮助,这是我的批处理更新代码
let batch=admin.firestore().batch();admin.firestore().collection('students').where('branch.id','==',documentId.).get().then((querySnapshot)=>{querySnapshot.forEach((doc)=>{batch.update(doc.ref,{branch:{id:documentId,name:after.name}});});return batch.commit();}).catch(err=>{console.log('error==>',err);})
但我的问题是如何使用where子句ex:
let student\u public=admin.firestore().collection('student\u public').where('branch.id','==',documentId')将相同的逻辑应用到许多文档中