【问题标题】:Only first document is returned as response instead of multiple documents using Firestore and Cloud Functions仅返回第一个文档作为响应,而不是使用 Firestore 和 Cloud Functions 的多个文档
【发布时间】:2021-05-26 02:37:18
【问题描述】:

我有这个快递功能:

exports.getSliderTipsteriData = (req, res) => {
  let sliderTipsteriData = [];
  db.collection("tipsterBanner")
    .orderBy("createdAt", "desc")
    .where("show", "==", true)
    .get()
    .then((data) => {
      data.forEach((doc) => {
        let eventId = doc.data().eventId;
        sliderTipsteriData = doc.data();
        db.collection("evenimenteTipsteri")
          .orderBy("createdAt", "desc")
          .get()
          .then((data) => {
            sliderTipsteriData.tipsteri = [];
            data.forEach((doc) => {
              if(doc.data().bilet[0].id === sliderTipsteriData.eventId) {
                sliderTipsteriData.tipsteri.push({
                  tipster: doc.data().tipster,
                  homeTeam: doc.data().bilet[0].homeTeam,
                  awayTeam: doc.data().bilet[0].awayTeam
                })
              } else null
            })
            return res.json(sliderTipsteriData);
          })
      })
    })
    .catch((err) => {
      console.error(err);
      res.status(500).json({ error: err.code });
    });
};

并收到此响应:

{
    "imageUrl": "https://firebasestorage.googleapis.com/v0/b/socialape-bea5b.appspot.com/o/slider1.jpg?alt=media&token=0824a93d-4bc3-49fa-9ae8-4408961a0736",
    "event_date": 1614110400,
    "awayTeamName": "Bayer Leverkusen",
    "awayTeamPercent": 23,
    "homeTeamName": "Atletico Madrid",
    "homeTeamShortName": "ATL",
    "awayTeamEmblem": "https://media.api-sports.io/football/teams/34.png",
    "createdAt": "2021-03-22T18:25:03.667Z",
    "homeTeamEmblem": "https://media.api-sports.io/football/teams/49.png",
    "awayTeamShortName": "LEV",
    "homeTeamPercent": "77",
    "show": true,
    "eventId": 652238,
    "homeTeamColor": "#0099ff",
    "awayTeamColor": "#ff0000",
    "etapa": "Liga Campionilor, Etapa 2",
    "tipsteri": [
        {
            "tipster": "daniel",
            "homeTeam": "Lazio",
            "awayTeam": "Bayern Munich"
        },
        {
            "tipster": "user",
            "homeTeam": "Lazio",
            "awayTeam": "Bayern Munich"
        }
    ]
}

问题是我在 tipsterBanner 集合中有多个文档,但我只收到第一个。所以 forEach 文档可能无法正常工作。

知道我在这里想念什么吗? 我希望收到具有多个对象的 sliderTipsteriData 数组作为响应,而不仅仅是第一个。看起来 forEach 实际上并没有循环。

【问题讨论】:

    标签: node.js express google-cloud-firestore google-cloud-functions


    【解决方案1】:

    这是因为您有承诺尝试在不等待它们的循环中运行。在您的 then 块内,您执行更多异步调用 (collection().get()),但您的代码并没有等待它们解决,所以它只是飞过您的 forEach 循环,创建这些承诺,然后到最后并返回。

    有两种方法可以解决这个问题 - (1) 将您的 then/catch 调用放入 Promise.all 并等待它解决或 (2) 切换到 async/await。但我认为你有一个更好的解决方案。现在,您在每个循环中查询您的evenimenteTipsteri 集合,但您没有使用来自tipsterBanner 集合的任何信息作为evenimenteTipsteri 查询中的参数,因此您可以只查询它们一次并且然后处理代码中的所有过滤/组织。这将有助于加快您的结果帮助您避免在 Firestore 上不必要的读取成本。

    此代码未经测试,因为我只是复制/粘贴您的代码并重写它而无法运行它,但这是主要思想:

    exports.getSliderTipsteriData = (req, res) => {
      let sliderTipsteriData = [];
    
      // These create the promises which will resolve in our Promise.all()
      const tipsterBanner = db.collection("tipsterBanner").orderBy("createdAt", "desc").where("show", "==", true).get()
      const evenimenteTipsteri = db.collection("evenimenteTipsteri").orderBy("createdAt", "desc").get()
    
      Promise.all([tipsterBanner, evenimenteTipsteri]).then((results) => {
        // results is now an array of your original "data" items from your then blocks
        // results[0] is the data from the tipsterBanner query
        // results[1] is the data from the evenimenteTipsteri query
        const tipsterBannerResults = results[0] // Just to make it more readable
        const evenimenteTipsteriResults = results[1] // Just to make it more readable
        tipsterBannerResults.forEach(doc => {
          let eventId = doc.data().eventId
          sliderTipsteriData = doc.data() // Is this right? You could end up overwriting your data
          sliderTipsteriData.tipsteri = []
          evenimenteTipsteriResults.forEach(doc => {
            if(doc.data().bilet[0].id === sliderTipsteriData.eventId) {
              sliderTipsteriData.tipsteri.push({
                tipster: doc.data().tipster,
                homeTeam: doc.data().bilet[0].homeTeam,
                awayTeam: doc.data().bilet[0].awayTeam
              })
            }
          })
        })
        return res.json(sliderTipsteriData)
      }).catch(error => {
        // Handle errors from your queries
      })
    }
    

    【讨论】:

    • 感谢您的回答,代码确实有效 :) 但我有相同的结果,如果我有 2 个带有 show = true 的集合,我只有一个,没有循环。我很确定我在这里覆盖了数据 sliderTipsteriData = doc.data()
    猜你喜欢
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    • 1970-01-01
    • 2023-03-29
    • 2021-03-16
    • 1970-01-01
    相关资源
    最近更新 更多