问题描述
在Flutter应用中,我在Cloud Firestore上有一个userData集合,用于存储用户的数据,包括名称,图像url等。用户可以创建帖子,在帖子中添加评论等,与其他任何社交应用类似在那里,所以我有多个其他集合,其中存储了用户信息,包括指向其个人资料图像的链接。
让我们说如果用户在帖子中添加评论,我会将其名称,个人资料图像网址和评论文本保存为文档“ postComment”集合中,然后在其上显示他/她的个人资料图像,姓名和评论文本通过阅读此收藏夹和文档在屏幕上显示。
现在,如果用户更新其个人资料图像或姓名(将反映在userData集合中),则我需要确保在所有其他集合中也都更新了他们的姓名和图像网址。
最简单,最省钱的方法是什么?我是否需要遍历所有集合及其文档并更新字段值,还是有一个简单的云函数可以处理此问题?
谢谢!
解决方法
我还将用户配置文件图像存储在Firestore存储中,但是我使用非常一致的架构来使图像易于“猜测”: 当我有一个诸如“ / People / {userID}”之类的文档时,在该文档中是一个“图像”字段,用于存储图像的URL。 ...然后我将其存储在Firestore中的路径“ People / {userID / image / image.jpg”(例如)。这样,生成一个指向它的StorageRef,和 downloadURL的过程就很简单。
它的所有其他用途始终是现在标准化的URL。更改存储中的图像;所有引用都会更新。
对于大多数“用户”应用程序,图像的唯一用途是将其馈送到网页,因此仅需要URL,然后让浏览器完成其余工作。
就像Fattie所说的那样,通常 您所需要的只是URL。但是仅凭其本身就意味着您 still 必须找到所有引用,并在用户更改URL时对其进行更新。将副本保存在Firestore存储中,并使用该一致的URL ,这意味着仅更改存储在该位置的内容即可“更新”所有引用。缺点是 在获取时将被视为存储读取。
我发现NoSQL中的重复数据是相当静态的-创建一次,并且不会动态更改(这是很多情况),这非常好。如果您的应用程序不合适,最好存储对真相源的引用,并承担“查找”的费用。
以下是我用来简化此操作的几个实用程序:
export const makeStorageRefFromRecord = (
record,key = null,filename = null
) => {
return FirebaseStorage.ref(
record.ref.path + (key ? "/" + key : "") + (filename ? "/" + filename : "")
);
};
export const makeFileURLFromRecord = (record,filename = null) => {
return FirebaseStorage.ref(
record.ref.path + (key ? "/" + key : "") + (filename ? "/" + filename : "")
).getDownloadURL();
};
(“键”本质上是字段名) 请记住,refpath是记录的用“ /”分隔的集合/文档路径的字符串,并且在简单的情况下(例如“ People / {userID}”)是完全可以理解的。如果将其保留在内部,则可以使用与“ image.jpg”一样简单的“文件名”,因此它始终是相同的-由于 path ,它是唯一的。
,我是否需要遍历所有集合及其文档并更新字段值
至少,是的,这就是您要做的。
还是有一个简单的云函数可以处理此问题?
您当然也可以编写自己的Cloud Function来做到这一点。没有一个现有的功能可以满足您的要求-您必须对其进行编码。
或者,您可以仅将URL存储为一个文档,将该文档的ID存储在需要引用该文档的其他文档中,然后让客户端使用所需的URL查询单个文档。 / p>
,有多种方法可以做到这一点。
最好的方法是不必存储一次又一次的个人资料图片图像,而可以存储文档参考。如果将图像存储为base64,则还可以节省空间并节省成本。
另一种方法效率较低,但是您可以将图像存储在Firestore中,然后从那里进行引用。
这两个都是来自裁判
最后一种可能也是效率最低的方法是查询。您可以转到该帖子集(或者,如果将每个帖子存储为一个帖子,则遍历所有帖子),然后添加一个where过滤器并搜索imageURL或更安全的唯一ID,然后就可以更改所有帖子一个人
这些是我所知道的方式