firebase 如何在Firestore中自动更新不同集合中的同一字段

hgqdbh6s  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(174)

我使用云Firestore作为我的数据库,我有users的集合,其中存储了有关用户的基本信息,如ID,名称,姓氏,电子邮件,公司ID。
我还有companies的集合,在每个公司我都有tasks的集合。在每个任务中,我从用户集合中分配了一个用户(用户数据被复制,所以我有与users集合中相同的用户数据)
问题是当我从集合users更新用户(更改名称或电子邮件...)时,因为数据被复制,该特定用户的tasks集合中的数据未更改。
有没有什么方法可以让firestore在users集合中的用户更新时自动更新到tasks集合中?

qxgroojn

qxgroojn1#

这在NoSQL数据库中是一种非常常见的情况,我们经常对数据进行非规范化处理,并且需要使这些数据保持同步
基本上有两种可能的主要方法:

#1客户端更新

当你更新“用户”文档时,同时更新包含用户详细信息的其他文档(即“任务”)。你应该使用批写来做到这一点:一批写入以原子方式完成,并且可以写入多个文档。
大致如下:

// Get a new write batch
var batch = db.batch();

var userRef = db.collection('users').doc('...');
batch.update(userRef, {name: '....', foo: '....'});

let userTaskRef = db.collection('companies').doc('...').collection('tasks').doc('taskId1');
batch.update(userTaskRef, {name: '....'});

userTaskRef = db.collection('companies').doc('...').collection('tasks').doc('taskId2');
batch.update(userTaskRef, {name: '....'});

// ...

// Commit the batch
batch.commit().then(function () {
    // ...
});

请注意,您需要知道哪些是“包含用户详细信息的其他(“任务”)文档”:你可能需要做一个查询来获取这些文档(以及它们的DocumentReference)。

#2通过云函数在后端更新

编写并部署一个云函数,当任何“用户”文档被更新时触发,并接受此“用户”文档的值,并更新包含用户详细信息的“任务”文档。
与第一种方法类似,在这种情况下,您还需要知道哪些是包含用户详细信息的“其他”(“任务”)文档。

  • 在您的评论(“是否有任何选项可以引用另一个表或放置外键?”)* 之后,这里是一个云函数,它将更新所有(“任务”)文档,这些文档的DocumentReference包含在“用户”文档中的专用Array字段taskRefs中。Array成员的数据类型为Reference
exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {

        const newValue = change.after.data();

        const name = newValue.name;
        const taskRefs = newValue.taskRefs;
        
        const promises = taskRefs.map(ref => { ref.update({ name: name, foo: "bar" }) });
        return Promise.all(promises);

    });

您最有可能在前端的“user”文档中设置此taskRefs字段的值。使用JS SDK时,可以按照以下方式进行设置:

const db = firebase.firestore();
db.collection('users').doc('...').set({ 
   field1: "foo",
   field2: "bar",
   taskRefs: [   // < = This is an Array of References
       db.collection('tasks').doc('....'),
       db.collection('tasks').doc('....')] 
 });

相关问题