Flutter 如何优化 Firestore 存储读取以防止大量不必要的读取

Posted

技术标签:

【中文标题】Flutter 如何优化 Firestore 存储读取以防止大量不必要的读取【英文标题】:Flutter how to optimise Firestore store reads to prevent a lot of unnecessary reads 【发布时间】:2020-07-03 14:08:36 【问题描述】:

我正在构建一个用户登录到应用程序时的位置,它会显示所有用户的信息,这些信息也在应用程序上注册。使用我的 init fetch 方法获取所有信息,它使用大量读取,在几天的测试中达到 1.3k 读取,而只有 4 个用户注册。这是异常高的。

我的 fetch 方法从 firestore 中获取用户信息

void loadUserProfiles() async 
    var firebaseUser = await FirebaseAuth.instance.currentUser();
    List<String> tempUsers = List<String>();
    List<String> tempNames = List<String>();
    List<String> tempImages = List<String>();

    imageUrl.clear();
    names.clear();
    userId.clear();

    tempUsers.clear();
    tempNames.clear();
    tempImages.clear();
    setState(() 
      isLoading = true; //Data is loading
    );

    // Adds all the values of each user from firestore to their list to compare
    await firestoreInstance
        .collection("users")
        .getDocuments()
        .then((QuerySnapshot snapshot) async 
      snapshot.documents.forEach((f) async 
        if (f.documentID != firebaseUser.uid) 
          tempUsers.add(f.data['userid']);
          tempNames.add(f.data['name']);
          tempImages.add(f.data['images'][0]);
        
      );
    );

    // Adds user to list to load to user cards if doesnt exist in liked users firestore
    for (int i = 0; i < tempUsers.length; i++) 
      await firestoreInstance
          .collection("users")
          .document(firebaseUser.uid)
          .collection("liked_users")
          .document(tempUsers[i])
          .get()
          .then((value) async 
        if (!value.exists) 
          userId.add(tempUsers[i]);
          names.add(tempNames[i]);
          imageUrl.add(tempImages[i]);
        
      );
    

    setState(() 
      isLoading = false; //Data has loaded
    );
  

我这样做的方式是它获取所有数据并将它们存储到三个单独的临时列表中。然后使用这些列表,我将再次阅读 firestore 以比较当前用户喜欢的用户 id 是否存在于集合中。

它也变得更糟,因为我使用底部导航栏,每当点击该页面时,它都会再次启动我的加载方法,该方法使用更多读取。

【问题讨论】:

您如何确定所有读取都来自这个单一操作?似乎不太可能在每个级别使用深度 2 和最大实体 4 的嵌套集合,它可以乘以多达 1300 个读取 很抱歉,我应该说得更清楚。我不是说它来自一个操作,我已经测试了几天,但我确信它不应该有 4 个用户那么高 下一次,尝试添加更多详细信息,例如您已测试的天数,甚至粗略估计您尝试运行此功能的次数 【参考方案1】:

你可以做几件事:

    分页 在您的代码getDocuments 中,您似乎正在检索每个用户。一般来说,对于大量的集合(通常是为了提供一个列表),我们会尝试只获取那些将出现在视图中的内容,比如前 20 个文档。一旦达到最大滚动范围,我们就会获取下一个 20。

    对于您的重新加载问题,请尝试使用initState 函数进行获取。将它放在某个地方,以便它只在需要时运行。我不知道您的应用程序结构,但让我们在我的应用程序中说。我将所有基本数据的初始检索都放在了我的初始登录逻辑中,而不是每次我们路由到需要数据的页面时都这样做

    此外,Google 还提供了有关 Cursors 等内容的官方指南。检查一下,看看其他解决方案是否更合适。

【讨论】:

您好,谢谢,我会看看您提出的建议。我的重新加载功能工作正常,因为我已将上述方法置于初始化状态,它只是每次在导航栏中单击该链接时都会运行初始化状态 哦,这是一个 Flutter Web 项目吗? 不,这是一个颤振应用项目。我是 Flutter 的新手 “initState”不应再次运行,即使“setState”也是如此。但是,我猜你的意思是你已经弹出了路由,推了另一个,然后用这个加载函数推回了一个。在这种情况下,您可以尝试检查您的列表是否仍被填写。如果是这样,则无需运行加载。除非您的应用程序后端节奏非常快且流量很大,并且预计会瞬间发生变化,否则每次页面重新启动时一次又一次地加载数据真的没有意义。 好的,我已经设法修复了初始化状态。我将如何监听新添加的用户到 Firestore,所以如果添加了新用户,那么初始化状态将运行。

以上是关于Flutter 如何优化 Firestore 存储读取以防止大量不必要的读取的主要内容,如果未能解决你的问题,请参考以下文章

如何使用flutter-web将时间戳存储在firestore中

Flutter:Google Maps 如何从 Firestore 设置图标

Firestore 和 Flutter:使用流优化数据读取

如何在flutter的firestore中使用uid更新用户数据

如何在 Firestore -Flutter 中将所有文档从一个集合复制到另一个集合?

Flutter:在 Firestore/实时数据库中存储和检索格式化文本