【问题标题】:How to get array of documentSnapshot from httpsCallable firestore function in JSON format如何从 JSON 格式的 httpsCallable firestore 函数获取 documentSnapshot 数组
【发布时间】:2020-09-08 15:13:15
【问题描述】:

所以我想在我的客户端应用程序上使用 httpsCallable 云函数加载 Firestore 文档。 之前我使用典型的getDocuments function 加载了我的文档,它返回了一组简单的 JSON 格式快照,如下所示:

Firestore.firestore().collection("users").getDocuments { (snapshot, err) in
if let err = err{
                print("Failed to load data from firebase:", err)
                return
            }
snapshot?.documents.forEach({ (documentSnapshot) in
// documentSnapshot.data() is in JSON format
...
    }
}

现在我想通过返回 httpsCallable 云函数来加载我的文档。所以我的云功能运行良好并返回了我的文档数据。但我遇到的问题是函数的返回格式。我从云函数收到的数据格式如下:

(
        {
        index = 34;
        field1 =         (
            "yes",
            "no",
            "maybe"
        );
        field2 = 26;
        brand = Puma;
        color = "marshmallow-natural";
        EcoFriendly = 1;
     },
      {
        index = 12;
        field1 =         (
            "oui",
            "non",
            "peut-être"
        );
        field2 = 21;
        brand = Nike;
        color = "red";
        EcoFriendly = 0;
     }
...
)

我通过如下调用函数观察到这一点:

functions.httpsCallable("smartShoeFinder").call([
        "vector": fireV[0]]) { (result, error) in
          
            if let error = error as NSError? {
            // Handle error
          }
            print(result?.data)
            //The following is my attempt towards extracting the data and
            // converting it to an array of JSON:
            let requestResult = result!.data
            if let swiftArray  = result!.data as! NSArray as? [Any] {
                print(swiftArray[0])
            }
            
  }

我希望我的数据是 JSON 数组:

[["index": 34, "field1": ["yes", "no", "maybe"], "field2": 26, "brand": "Puma", "color" = "marshmallow-natural", "shoeEcoFriendly": 1], 
["index": 12, "field1": ["oui", "non", "peut-être"], "field2": 21, "brand": "Nike", "color" = "red", "shoeEcoFriendly": 1]]

之前格式是一组简单的 JSON 字典(如上所示),可轻松转换为我的不同客户端对象。 现在它是一个 __NSArrayM(即 apparently 一个 NSMutableArray)。 那么你知道我是否可以在 JSON 数组中返回我的 httpsCallable firestore 函数吗?就像下面的请求一样:

Firestore.firestore().collection("users").getDocuments{ (snapshot, err) in
    snapshot?.documents.forEach({ (documentSnapshot) in
    documentSnapshot.data() // I'd like it in this format
    }
}

我的 firestore 函数返回以下数据 (TypeScript) 的 数组

const db = admin.firestore();
export const smartShoeFinder = functions.https.onCall(async (data, context) => {
let outputDocuments = new Array()
const collection = await db.collection('collection')
const notVisited = [1,32,13,44,15,26]
for (const index of notVisited){
    console.log(index)
    const snap = await collection.where("index", "==", index).get()
    if (snap.size == 0){
       continue
       }
    const onlyDoc = snap.docs[0].data
    outputDocuments.push(onlyDoc) // Populating the array with the wanted documents
  }
// Now returning promise to the client
.then(() => {
    return new Promise((resolve, reject) => {
        resolve(outputDocuments)
    })
})
.catch(err => console.log(err))
})

其中 outputDocuments 是文档数据的数组。

有没有更好的方法来做到这一点?

【问题讨论】:

  • 除了调用它的客户端代码之外,请编辑问题以显示未按预期方式工作的函数的完整代码。这三行 sn-p 不足以看到它在做什么。问题中应该有足够的信息,以便任何人都可以重现该行为。
  • 好了,函数的精华我加了。我真的很喜欢你的 Firebase 视频,顺便说一句道格,非常感谢你的这些!今天早上我只是在看那些功能!
  • 调用这个函数的客户端代码是什么?您如何观察结果,这与您的预期有何不同?
  • 我在编辑中回答了您的问题。谢谢
  • 如果不是您所期望的,您的客户端代码会打印什么?

标签: swift typescript google-cloud-firestore google-cloud-functions


【解决方案1】:

我是一名 JavaScript 开发人员,对 Swift 的了解有限,但您可以像这样简化代码:

const db = admin.firestore();

exports.smartShoeFinder = functions.https.onCall(async (data, context) => {
    // FROM CLIENT AS AN ARRAY OF INTEGERS
    const notVisited = data.notVisited;     

    function getDoc(index){
        // RETURNS THE QUERY WHICH IS ALREADY A PROMISE SO NO NEED TO WRAP IT
        return db.collection('collection').where("index", "==", index).get().then(colSS=>{
            if (r.empty){
                return {
                    isEmpty: true
                };
            }
            else{
                return {
                    isEmpty: false,
                    doc: r.docs[0].data()
                };
            }
        }).catch(e=>{
            console.log("QUERY ERROR: " + e.message);
        })
    }
    // STORES ALL QUERIES IN AN ARRAY OF PROMISES
    let processes = notVisited.map(index=>{
        return getDoc(index);
    })
    // USE Promise.all() TO RESOLVE ALL THE PROMISES IN PARALLEL
    return Promise.all(processes).then(result=>{
        // FILTER OUT THE NON EMPTY ONES AND EXTRACT THE DATA.
        return result.filter(query=>{
            return !query.isEmpty;
        }).map(query=>{
            return query.doc;
        })
    })
})

或者,仅当您的未访问索引数组的长度在 10 个元素以内时,可以进一步简化它,使用 array-contains-any 查询并将“索引”字段转换为单个元素的数组(您需要为每个元素事先准备文件)像这样:

const db = admin.firestore();

exports.smartShoeFinder = functions.https.onCall(async (req, context) => {
    return await db.collection("collection").where("index", "array-contains-any", data.notVisited).then(colSS=>{
        return colSS.docs.map(docSS=>{
            return docSS.data();
        })
    })
})

【讨论】:

    猜你喜欢
    • 2018-03-28
    • 1970-01-01
    • 2011-06-02
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 2018-08-02
    • 2018-07-07
    • 2015-07-09
    相关资源
    最近更新 更多