Reputation: 63
Im trying to retrieve some data from firestore within a cloud function, but get nothing back. The same query on the client-side gives me the correct results. It's probably something small but I don't see the issue. What am I doing wrong?
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
db.settings({ timestampsInSnapshots: true });
exports.myFunction = functions.https.onCall((data, context) => {
const info = getInfo();
//do some stuff with the info
return info;
}
function getInfo() {
const query = db
.collection('info')
.where('table_nr', '==', 1)
.where('number', '<=', 25)
.orderBy('number', 'desc')
.limit(1);
const info = query.get().then(snapshot => {
snapshot.forEach(doc => {
return doc.data();
})
})
return info;
}
When I make a call to this function I get: "data: null"
let info = functions.httpsCallable('myFunction')
info().then(res => { console.log(res) })
I tried a lot of different options, like when I change the last part to:
const info = query.get().then(snapshot => {
snapshot.docs;
})
I get an array with 1 object. So I'm sure there is a document in the query with data. The console.log gives me:
{data: Array(1)}
data: Array(1)
0: {_ref: {…}, _fieldsProto: {…}, _serializer: {…}, _validator: {…},
_readTime: {…}, …}
length: 1
__proto__: Array(0)
__proto__: Object
And:
return query.get().then(querySnapshot => {
if (querySnapshot.empty) {
return { exists: false }
} else {
return { exists: true }
}
})
The console.log:
{data: {…}}
data:
exists: true
__proto__: Object
__proto__: Object
Mabye good to add that I created an (working) index for the query.
Upvotes: 4
Views: 4959
Reputation: 993
So to give a clear example of using the .where in the Firebase Functions library for Firebase Cloud Functions
admin.firestore().collection("fruit")
.where("color", "==", "purple")
With ordering
admin.firestore().collection("fruit").orderBy("size")
.where("color", "==", "purple")
See demo doc if you want more details about how admin functions
Furthermore, the list of all query functions are found in the Query class can be used from the Firestore Functions library by using method chaining like my two examples in case you'd like things like "limit", "offset", etc.
Upvotes: 0
Reputation: 317352
In both cases, you're returning a promise for an object that isn't what you really want to send to the client. When you write a callable, you need to return a promise that resolves to the exact JavaScript object that you want to send. You can't just return anything. What you'll have to do is convert that querySnapshot into plain old JavaScript objects that describe what you want the client to know. A querySnapshot object itself is not serializable - it is a complex object that describes many things about the query results.
First define this: What exactly do you want the client to receive? Define what the actual JavaScript object should look like. Now, convert the query results to look like that. At a minimum, you can send the entire set of documents as plain JS objects like this:
return query.get().then(querySnapshot => {
return querySnapshot.docs.map(doc => doc.data());
})
This will return an array to the client with raw document objects. But it's not clear to me that's what you want to send (since you didn't define your expectations). But it's a start.
Upvotes: 7