【问题标题】:How to filter data of a big Firestore list?如何过滤大型 Firestore 列表的数据?
【发布时间】:2021-07-06 21:49:27
【问题描述】:

在以下代码中,我从 Firestore 数据库中获取用户并将它们传递给视图。视图有一个输入字段,用于在您输入时搜索用户并过滤结果:

import React, { useState, useEffect } from "react";
import axios from "axios";

export default function App() {
  const [users, setUsers] = useState([]);
  const [search, setSearch] = useState("");

  useEffect(() => {
    firebase
    .firestore()
    .collection('users')
    .onSnapshot((fetchedUsers) => {
       setUsers(fetchedUsers.docs.map((user) => user.data()));
    }).catch((error) => {
       // error handling
    });
  }, [setUsers]);

  return (
    <div className="App">
      <input
        type="text"
        placeholder="Search User..."
        value={search}
        onChange={(e) => setSearch(e.target.value)}
        style={{ marginBottom: "30px" }}
      />
      {users
        .filter((e) => e.name.toLowerCase().includes(search.toLowerCase()))
        .map((user) => (
          <div>{user.name}</div>
        ))}
    </div>
  );
}

我正在从 Firestore 中获取用户,并且每天都会添加 1000 多个用户。因此,对用户列表的每次访问都算作 Firestore 读取次数。

如何减少阅读量,而不会失去在输入时搜索用户的可能性?我正面临这个问题,因为当我添加分页或仅获取最近的 50 个用户时,我没有可用于过滤的完整列表。

【问题讨论】:

    标签: reactjs google-cloud-firestore


    【解决方案1】:

    在查看 firestore 文档时,我发现它具有查询支持。

    https://firebase.google.com/docs/firestore/query-data/queries#simple_queries

    如果我的理解是正确的,你需要过滤掉结果,这可以委托给firestore。

    要减少对 Firestore 的调用次数,您可以实现 debounce。

    【讨论】:

    • 我认为这可以解决我的问题。在我的真实应用中,我已经在使用 Firestore。但我想避免一次获取所有用户,因为有很多用户。但是当我想被动地过滤它们时,我有些需要全部 - 只有在我过滤时才需要它们。
    • @T.Karter “Bcz 我不能对上面的帖子发表评论,在这里;这对你有用”基本上你自己回答了这个问题。您需要结合使用过滤和限制(想想分页),但这需要直接在 Firestore 上发生。 Bcz 您想减少读取,您无法在客户端 1 上获取所有数据和过滤。在 Firestore 上查询 2. 限制结果 3. 分页 firebase.google.com/docs/firestore/query-data/queries firebase.google.com/docs/firestore/query-data/order-limit-data firebase.google.com/docs/firestore/query-data/query-cursors
    • 上面加上去抖动,你可以进一步减少调用次数。
    • 您的意思是将超时答案与去抖动配对?你能举个例子吗?
    【解决方案2】:

    通过阅读您的问题,您似乎希望在用户输入输入元素时限制对您的 Firestore 的调用。为此,我将使用useEffect 中的setTimeout 函数来延迟调用firestore,直到用户停止输入后500 milliseconds。 useEffect 函数的变化如下。

    实现超时功能后,您需要使用where 功能过滤您的数据。此函数接受三个参数([search for], '[operator]', [what to match]),因此,在您的情况下,您将拥有('name', '==', search)。查看下面的代码,and check out the documentation for firestore queries。

    useEffect(() => {
    
     // Adding the search variable to the array of the second useEffect argument
     // will cause this useEffect to run on every change to the search variable, which
     // is what we want since we do not know when the user will stop typing.
    
     // Also to filter user's, use the 'where' function, which has three parameters.
    
     const timeout = setTimeout(() => {
      firebase
        .firestore()
        .collection('users')
        .where('name', 'in', search)
        .onSnapshot((fetchedUsers) => {
           setUsers(fetchedUsers.docs.map((user) => user.data()));
        .catch(err => {
          // catch error
        });
     }, 500);
    
     // Clean up timeout
     return () => clearTimeout(timeout)
    
    }, [search, setUsers]);
    

    【讨论】:

    • 我不确定是否需要重新表述我的问题。我有例如2.000 个用户,目前我获取所有用户,这意味着 2.000 次读取。例如,我可以添加分页以仅获取 10。这基本上是我想要的,但是当我这样做时,我无法使用过滤器,因为我只有 10 个用户要过滤,我想过滤所有用户。
    • @T.Karter 所以基本上,您的过滤器会遍历所有 2,000 个用户以找到符合特定条件的用户,而您不希望它正确吗?
    • 这就是重点——我会说我需要所有用户都能够过滤它们。但我并不总是过滤。用分页显示最后 10 个用户就可以了。所以基本上第一次获取有一个.limit(10)。但是当我现在想过滤时,我需要所有我想的。或者在 Firestore 中有一个过滤技巧,只读取过滤后的结果。
    • 我不知道firestore API,但是如果您要获取每个请求的所有2,000个用户并在您的React应用程序中过滤它们,您需要找到过滤器方法火库 API。原因是,随着应用程序中用户数量的增加,您可能会强制客户端在每次搜索时对数千名用户进行排序,这对性能非常不利。
    • @T.Karter 我编辑了我的答案,希望对您有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2022-10-01
    • 1970-01-01
    • 2020-02-12
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 2016-10-16
    • 1970-01-01
    相关资源
    最近更新 更多