所以我想在我的客户端应用程序上使用httpsCallable云函数加载firestore文档Before我用一个典型的getDocuments函数加载了我的文档,它返回了一组简单的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字典(如上所示(,可以很容易地转换为我的不同客户端对象现在它是一个__NSArray(显然是一个NSMutableArray(那么你知道我是否可以在JSON数组中获得httpsCallablefirestore函数的返回吗就像以下请求一样:
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))
})
其中outputDocument是文档数据的数组。
有更好的方法吗?
我是一名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;
})
})
})
或者,仅当您的notVisited索引数组的长度在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();
})
})
})