Google Pub/Sub 更新 Firestore 子集合

Posted

技术标签:

【中文标题】Google Pub/Sub 更新 Firestore 子集合【英文标题】:Google Pub/Sub update Firestore sub collection 【发布时间】:2020-03-27 06:12:42 【问题描述】:

我正在尝试每 2 分钟更新一次子集合中的字段。如果时间戳早于 3 分钟,我将字段“状态”更改为“关闭”。我有这段代码,有人帮助我,它适用于集合,但我不知道使用什么集合路径来访问其中包含此子集合的所有文档。

5 分钟后,如果时间戳超过 3 分钟,我希望“状态”字段为“关闭”。

const snap = await db.collection("MX") 有效,但仅适用于 1 层深。 userProfiles 中的每个文档都有一个 MX 的子集合。

我尝试了通配符和几种不同的收集路径。

exports.updateIdle = functions.pubsub.schedule('every 2 minutes').onRun(async () => 

const db = admin.firestore();
// this is what line I am trying to figure out
  const snap = await db.collection("userProfiles") 
    .where("Status", "=", "On")
    .where("Timestamp", "<", admin.firestore.Timestamp.fromMillis(Date.now() - 3 * 60000))
    .get();


  await Promise.all(snap.docs.map(doc => doc.ref.update(Status: 'Off')));

  console.log('this goes off every two minutes')
); 

编辑: userProfile -> 每个文档 -> 4 个子集合(MX、员工、设置、日志)

我在 MX 中存储了文档。这些文档将具有状态和时间戳。

我希望这个 pub/sub 检查存储在 MX 子集合中的所有文档。

如果时间戳是 3-5 分钟,并且状态 = 开启。我想将状态更改为关闭

所以我正在检查所有 MX 子集合。在这种情况下,userProfiles 中有 4 个文档,每个文档中都有一个 MX 子集合。

我感谢任何和所有的帮助。我希望我能很好地解释这一点。谢谢。

【问题讨论】:

您是否确认,换句话说,您正在寻找一种解决方案来查找具有MX 子集合的MX 集合的文档 是的。 userProfiles 中的所有文档都有一个我想访问的 MX 子集合。 而且您知道这些文档确实有一个 MX 集合。您的问题是如何访问此 MX 集合的文档? 另外,userProfileMX 子集合中是否有您要更新的特定文档?或者您想更新此userProfile/MX 子集合的所有文档? 是的。我希望这个 pub/sub 查看“MX”中的所有文档,如果“时间戳”超过 3 分钟,我想将“状态”更改为“关闭” 【参考方案1】:

如果您想“更新任何具有旧时间戳的 MX 子集合中的所有文档”,则应使用 Promise.all()

exports.updateIdle = functions.pubsub.schedule('every 2 minutes').onRun(async () => 

    const db = admin.firestore();

    const querySnapshot = await db.collection("userProfiles") 
        .where("Status", "=", "On")
        .where("Timestamp", "<", admin.firestore.Timestamp.fromMillis(Date.now() - 3 * 60000))
        .get();
    
    const promises = [];
    querySnapshot.forEach(doc => 
        const docRef = doc.ref;
        promises.push(docRef.collection('MX').get());
    );
    
    const snapshotArrays = await Promise.all(promises);
    // snapshotArrays contains an array of arrays of QueryDocumentSnapshots

    const promises1 = [];
    
    snapshotArrays.forEach(snapArray => 
        snapArray.forEach(snap => 
            promises1.push(snap.ref.update(
                Status: "Off"
            ))
        )
    );
    
    return Promise.all(promises1);
    
);

当然,我假设您最初查询带有“timestamp that is old”的 userProfile 文档是正确的。


根据您的评论更新

我了解“时间戳为 3-5 分钟旧,并且状态 = 开启”的过滤将在 MX 文档级别进行。那么以下应该可以工作(我们只是将where 子句移动到MX 集合中)。但请注意,在这种情况下,我们会读取所有 userProfile 文档(每次读取都需要读取标准文档)。

exports.updateIdle = functions.pubsub.schedule('every 2 minutes').onRun(async () => 

    const db = admin.firestore();

    const querySnapshot = await db.collection("userProfiles").get();

    const promises = [];
    querySnapshot.forEach(doc => 
        const docRef = doc.ref;
        promises.push(docRef.collection('MX').where("Status", "=", "On")
        .where("Timestamp", "<", admin.firestore.Timestamp.fromMillis(Date.now() - 3 * 60000)).get());
    );

    const snapshotArrays = await Promise.all(promises);
    // snapshotArrays contains an array of arrays of QueryDocumentSnapshots

    const promises1 = [];

    snapshotArrays.forEach(snapArray => 
        snapArray.forEach(snap => 
            promises1.push(snap.ref.update(
                Status: "Off"
            ))
        )
    );

    return Promise.all(promises1);

);

如果您仍然遇到错误,请尝试不使用以下 where 子句,并重新定义您的 where 子句以获得所需的 MX 文档选择。

//....
const querySnapshot = await db.collection("userProfiles").get();

const promises = [];
querySnapshot.forEach(doc => 
    const docRef = doc.ref;
    promises.push(docRef.collection('MX').get());
);
//....

【讨论】:

我没有收到任何错误,并且响应为“ok”,但状态字段永远不会改变。我共享的代码有效,但仅在集合深度为一级时才有效。 (一个集合一个文档) 抱歉,我很难理解您到底在寻找什么。您说“userProfiles 中的所有文档都有一个我想访问的 MX 子集合”。恕我直言,这就是答案。如果不符合您的要求,能否在您的问题中添加一些图表或非常详细的文字说明? 请注意,我已经更新了答案:我忘记了这段代码要在云函数中执行!!所以我们应该返回最后一个Promise.all()返回的Promise。查看更新:return Promise.all(promises1); 非常感谢您的宝贵时间。我使用了最新的代码,并且发生了同样的情况。没有错误并以“ok”响应。我在帖子中添加了一个编辑。应该达到和更改的文档的一个示例是... /userProfiles/NBjjCvhBrkUEnvxvMbQouHTuwrI2/MX/Here .. 这是一个很大的帮助,所以如果我没有回答任何问题,请告诉我,我会尝试重新解释 感激不尽!!完美运行。再次感谢!!

以上是关于Google Pub/Sub 更新 Firestore 子集合的主要内容,如果未能解决你的问题,请参考以下文章

将 BigQuery 表流式传输到 Google Pub/Sub

在 Google Cloud Pub/Sub 中处理订阅过滤器更改的最佳方式是啥?

javascript Google Cloud函数用于在pub / sub和pub / sub到Big查询中发布数据

从 Google Pub/Sub 调用 Google App Engine 端点

访问 Google Cloud Storage 触发事件“Pub/Sub”?

Google Pub/Sub Java 示例