使用主文档从 Firestore 子集合中获取第一个文档?

时间:2021-06-29 08:51:23

标签: node.js google-cloud-firestore

我正在使用 Node.js(我很新)和 Google Cloud Firestore 数据库根据以下内容保存文档:

  • 用户
  • 推文

一个用户文档,即一个用户,在子集合“推文”中有许多推文。我有兴趣将用户与子集合中的最后一条推文一起检索,因此我得到了这样的 JSON 文件。换句话说,这就是我想要的

import geopandas as gpd
import geoplot as gplt

nb = r'C:\Users\XX\Downloads\[![Counties_and_Unitary_Authorities_(December_2017)_Boundaries_UK.shp][1]][1]'
regions = gpd.read_file(nb)
regions.sample(5)
gplt.polyplot(regions)

我有这个功能:

users: {
    {
    name:'john',
    twitter_username:'johnny',
    tweets: {
    text: "I am called johnny, this is my tweet",
    created_at: "2021-06-29 12:00:00"
    },
    },
    {
    name:'anne',
    twitter_username:'anne',
    tweets: {
    text: "I am called anne, this is another tweet",
    created_at: "2019-06-28 12:00:00"
    },
    }
}

如果我可以用最后一条推文获取并替换 doc.id(即用户文档 ID),我想可以解决它。但我该怎么做?

任何其他解决方案,可能带有 for 循环,也可以。我在这个看似简单的问题上花了几个小时,但无法让它同时返回用户数据和推文数据。

编辑 2:

我意识到我可以这样做:

   function getUserData() {
       return db.collection('users').get()
            .then((querySnapshot) => {
                var docs = querySnapshot.docs.map(doc => [doc.data(), doc.id]);         
                //console.log(docs);
                return docs

产生的日志结果为:

function getUserData() {
   return db.collection('users').get()
        .then((querySnapshot) => {
            var docs = querySnapshot.docs.map(doc => [doc.data(), doc.id, getStuff(doc.id)])
            console.log(docs)
            return docs                          
        });
}

function getStuff(doc_id) {
   return db.collection('users').doc(doc_id).collection('tweets').limit(1).get()
        .then((querySnapshot) => {
            var docs = querySnapshot.docs.map(doc => doc.data());         
            console.log("TWEETS", doc_id, docs[0]['text']);
            return docs[0]['text']
        });   
}

来自 getStuff 函数。

现在唯一的问题是我无法让 map 函数等待 getStuff,因此 TWEETS DAU86mxIhmD6qQQpH4F God’s country! TWEETS JQHTO0jUjAodMQMR6wI I’m almost there Danny! 返回 return docsPromise { <pending> }

我不熟悉 Promises 和 await/async,我无法让它发挥作用。解决这个 Promise pending -> twitter text 将解决我的问题。我该怎么做?

1 个答案:

答案 0 :(得分:1)

如果你想获取单个用户的数据,你可以写这样的代码:

const getUserData = async (userUid) => {
  const userSnap = await db.collection("users").doc(userUid).get();
  const tweetSnaps = await db
    .collection("tweets")
    .orderBy("created_at", "desc")
    .limit(1)
    .get();

  let tweet = {};

  tweetSnaps.forEach((doc) => {
    tweet = doc.data();
  });

  return {
    ...userSnap.data(),
    ...tweet,
  };
};

我们首先获取用户,然后查询最后一条推文并获取。我们按 tweetscreated_at 集合进行排序,并将其限制为单个文档。

如果您想一次为所有用户获取相同的数据,我们需要稍微更改代码,但逻辑是相同的。

如果数据保存在单独的集合中,则无法在单个数据库请求中获取它们。

编辑 2 的更新

这里您的代码在正确的 async/await 下应该是什么样子:

const getUserData = async () => {
  const querySnapshot = await db.collection("users").get();

  const docs = querySnapshot.docs;

  for (let i = 0; i < docs.length; i++) {
    const element = docs[i];
    doc.data(),
    doc.id,
    await getStuff(doc.id),
  }

  console.log(docs);
  return docs;
};

const getStuff = async (doc_id) => {
  const querySnapshot = await db
    .collection("users")
    .doc(doc_id)
    .collection("tweets")
    .limit(1)
    .get();

  var docs = querySnapshot.docs.map((doc) => doc.data());
  console.log("TWEETS", doc_id, docs[0]["text"]);
  return docs[0]["text"];
};