NodeJS 从URL中检索JSON并将其转换为Cloud Firestore Collection with Cloud Functions

nwo49xxi  于 2023-06-05  发布在  Node.js
关注(0)|答案(1)|浏览(122)

以下是我想要实现的:我想每天从URL中获取一个JSON,并将其转换为云Firestore集合,以便能够在我的Flutter应用程序中使用它。理想情况下,脚本只会向集合中添加新数据。
我看到我可以使用Firebase云函数中的scheduler来每天运行任务。这不是目前的问题。
但是,我不知道如何正确使用Firebase云函数从URL中获取数据并将其转换为集合。也许这不是云函数的重点,我误解了一些东西。第一个问题**我可以在云函数中运行经典nodeJS吗?我想我可以
接下来,我在本地初始化了一个云函数项目,将其连接到我的Google帐户,并开始将代码写入index.js

const functions = require("firebase-functions");
const admin = require('firebase-admin');
const fetch = require('node-fetch');

const db = admin.firestore();
const collectionToiletRef = db.collection('mycollection');

let settings = { method: "Get" };

let url = "my-url.com"

fetch(url, settings)
    .then(res => res.json())
    .then((json) => {
        print(json);
        // TODO for each json object, add new document
    });

第二个问题:**如何运行此代码,看看它是否有效?**我看到模拟器可以使用,但我如何查看我的云firestore集合?在这个简单的例子中,我只想打印我的json,看看我是否可以正确地获取数据。印刷在哪里进行?
也许云功能不是我需要的任务。也许我的代码是错误的。我不知道。谢谢你的帮助

编辑

我试过了,但电话永远不会结束。我想它是在等待一个永远不会回来的承诺或类似的事情。

const functions = require("firebase-functions");
const admin = require('firebase-admin');
const fetch = require('node-fetch');

admin.initializeApp();

const db = admin.firestore();

exports.tempoCF = functions
    .firestore.document('/tempo/{docId}')
    .onCreate(async (snap, context) => {
        console.log("onCreate");

        let settings = { method: "Get" };

        let url = "https://opendata.paris.fr/api/records/1.0/search/?dataset=sanisettesparis&q=&rows=-1"
        try {
            let response = await fetch(url, settings);
            let json = await response.json();
            // TODO for each json object, add new document
            await Promise.all(json["records"].map(toiletJsonObject => {
                return db.collection('toilets').doc(toiletJsonObject["recordid"]).set({}); // Only to create documents, I will deal with the content later
            }));
        }
        
        catch(error) {
            console.log(error);
            return null;
        }
    }
    );

这段代码可以工作,并创建我想要的所有文档,但永远不会返回。但是,传递给onCreateasync (snap, context) => {}是一个Promise。这个promise在Promise.all结束时结束。我错过了一些东西,但我不知道为什么。我在用Dart或JS进行异步编程时遇到了很多困难。我脑子里不是很清楚。

3z6pesqy

3z6pesqy1#

我可以在云函数中运行经典的nodeJS吗?
当然!因为fetch方法返回一个Promise,你可以很好地在后台触发或计划的云函数中使用它。
如何运行此代码以查看它是否有效?
您的代码将在emulator suite中完美运行,但您需要使用可以在模拟器中运行的Firebase服务之一触发Cloud Function。例如,您可以通过在Firestore仿真器控制台中创建文档来触发Cloud Function。
下面的云函数可以实现这一点:只需在虚拟tempo集合中创建一个文档,CF就会在newDocs集合中添加一个新文档。这取决于你来调整这个文档的字段值,我刚刚使用了整个JSON对象。

exports.tempoCF = functions
    .firestore.document('/tempo/{docId}')
    .onCreate((snap, context) => {

        let settings = { method: "Get" };

        let url = "https://..."

        return fetch(url, settings)
            .then(res => res.json())
            .then((json) => {
                console.log(json);
                // TODO for each json object, add new document

                return admin.firestore().collection('newDocs').add(json);

            })
            .catch(error => {
                console.log(error);
                return null;
            });
    });

您也可以将Cloud Function部署到Firebase后端,如果您想调度它,只需按如下所示更改代码(更改触发器):

exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {

        let settings = { method: "Get" };

        let url = "https://..."

        return fetch(url, settings)
            .then(res => res.json())
            .then((json) => {
                console.log(json);
                // TODO for each json object, add new document

                return admin.firestore().collection('newDocs').add(json);

            })
            .catch(error => {
                console.log(error);
                return null;
            });
    });

编辑后再编辑:

下面的代码在模拟器中正确工作,在toilets集合中创建文档。

exports.tempoCF = functions.firestore
    .document('/tempo/{docId}')
    .onCreate(async (snap, context) => {
        console.log('onCreate');

        let settings = { method: 'Get' };

        let url =
            'https://opendata.paris.fr/api/records/1.0/search/?dataset=sanisettesparis&q=&rows=-1';
        try {
            let response = await fetch(url, settings);
            let json = await response.json();

            return Promise.all(   // Here we return the promise returned by Promise.all(), so the life cycle of the CF is correctly managed
                json['records'].map((toiletJsonObject) => {
                    admin
                        .firestore()
                        .collection('toilets')
                        .doc(toiletJsonObject['recordid'])
                        .set({ adresse: toiletJsonObject.fields.adresse });
                })
            );
        } catch (error) {
            console.log(error);
            return null;
        }
    });

相关问题