【问题标题】:Get all records from collection with all refrences in Firestore从集合中获取所有记录以及 Firestore 中的所有引用
【发布时间】:2021-07-08 16:19:33
【问题描述】:

您好,我目前被阻止,因为我无法从具有 references 值的集合中获取所有记录。

我想从集合events 中获取所有记录(它有效),但是当我想合并与categoryId 关联的category 信息时,我的代码不再有效。

事件集合

分类集合

export const getEventsRequest = async () => {
  const output = [];
  const data = await firebase.firestore().collection('events').get();

  data.forEach(async (doc) => {
    const {
      name,
      address,
      city,
      duration,
      level,
      startDate,
      maxPeople,
      categoryId,
    } = doc.data();

    const { name: categoryName, color } = (
      await firebase.firestore().collection('categories').doc(categoryId).get()
    ).data();

    output.push({
      name,
      address,
      city,
      duration,
      level,
      startDate,
      maxPeople,
      category: { name: categoryName, color },
    });
  });

  return output;
};

React Native 项目中的示例测试

  const [events, setEvents] = useState([]);
  const [isEventsLoading, setIsEventsLoading] = useState(false);

  const getEvents = async () => {
    setEvents([]);
    setIsEventsLoading(true);

    try {
      const evts = await getEventsRequest();
      setEvents(evts);
      setIsEventsLoading(false);
    } catch (e) {
      console.error(e);
    }
  };

  useEffect(() => {
    getEvents();
  }, []);

  console.log('events', events);

输出

events Array []

预期

events Array [
  {
    name : "blabla",
    address: "blabla",
    city: "blabla",
    duration: 60,
    level: "hard",
    startDate: "13/04/2021",
    maxPeople: 7,
    category: {
      name: "Football",
      color: "#fff"
    },
  },
  // ...
]

我不知道是否有更简单的方法来检索这种数据(例如mongo DB上有populate方法)。

提前感谢您的回答。

【问题讨论】:

    标签: javascript reactjs firebase react-native google-cloud-firestore


    【解决方案1】:

    当您使用CollectionReference#get 时,它会返回一个包含QuerySnapshot 对象的Promise。此类上的 forEach 方法与 Promise/async 不兼容,这就是您的代码停止按预期工作的原因。

    您可以做的是,使用QuerySnapshot#docs 获取集合中的文档数组,然后创建一个处理每个文档的Promise-returning 函数,然后将其与Promise.all 一起使用以返回数组处理过的文件。

    最简单的形式是这样的:

    async function getDocuments() {
      const querySnapshot = await firebase.firestore()
        .collection("someCollection")
        .get();
    
      const promiseArray = querySnapshot.docs
        .map(async (doc) => {
          /* do some async work */
          return doc.data();
        });
    
      return Promise.all(promiseArray);
    }
    

    将其应用于您的代码给出:

    export const getEventsRequest = async () => {
      const querySnapshot = await firebase.firestore()
        .collection('events')
        .get();
    
      const dataPromiseArray = querySnapshot.docs
        .map(async (doc) => {
          const {
            name,
            address,
            city,
            duration,
            level,
            startDate,
            maxPeople,
            categoryId,
          } = doc.data();
    
          const { name: categoryName, color } = (
            await firebase.firestore().collection('categories').doc(categoryId).get()
          ).data();
    
          return {
            name,
            address,
            city,
            duration,
            level,
            startDate,
            maxPeople,
            category: { name: categoryName, color },
          };
        });
    
      // wait for each promise to complete, returning the output data array
      return Promise.all(dataPromiseArray);
    };
    

    【讨论】:

    • 非常感谢@samthecodingman,它有效!我认为有一种最简单的方法可以实现这一目标。
    • @ThomasLeNaour 请注意,如果类别不存在,此代码将中断。您还可以通过缓存类别获取承诺来进一步优化它。
    猜你喜欢
    • 2018-06-23
    • 2021-09-17
    • 1970-01-01
    • 2020-08-08
    • 2021-07-29
    • 2018-03-18
    • 1970-01-01
    • 2019-02-05
    相关资源
    最近更新 更多