Closed NickCarducci closed 4 years ago
Hey, so I want to make sure I understand the issue here... Are you looking for an example of how to provide an endpoint that can make a geoquery while using CORS?
CORS is required for a Google Cloud Function POST, so yes. I want to use Google Cloud Function to query geofirestore data... Oh let me be clear I have used the CORS before, this code works. the data is there... I've never queried data like this though, snapshots & such
So the CORS aspect works, but the query doesn't?
For sure, near the query I commented [tried this] [instead of this] to show 2nd and 1st try using your query examples from other posts like these
So I'm just guessing but this may be because I need to have the instance run for longer than 8-10 minutes which is the longest a cloud function can run. An alternative for Google users would be google app engine \ gcloud init \ gcloud app deploy --verbosity=debug, which I am just learning now to deploy my websocket server in another feature. maybe I can & should use that instead so I can use nodejs runtime. I forget why I stopped trying to load geofirestore directly to the front-end reactjs. I'll read-up again and update within a week
Ok, so looking over your code I believe the issue has to do with how you're writing your then
statements to resolve your promises. So here's an example function I wrote that looks similar to what you had (I just skipped the CORS aspect, but since you're comfortable writing that bit of code I'm sure you can re-add it).
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const GeoFirestore = require('geofirestore').GeoFirestore;
admin.initializeApp();
const firestoreRef = admin.firestore();
const geofirestore = new GeoFirestore(firestoreRef);
const geocollection = geofirestore.collection('planner');
exports.chooseCity = functions.https.onRequest(async (request, response) => {
if (request.method === 'OPTIONS') {
response.set('Access-Control-Allow-Methods', 'POST');
return response.status(200).send({});
} else {
const radius = request.body.distance;
const center = new admin.firestore.GeoPoint(request.body.location[0], request.body.location[1]);
// The data from a doc is returned as a function, so you just need to map and call the function
const sendit = (await geocollection.near({ center, radius }).get()).docs.map((doc) => ({ ...doc, data: doc.data() }));
return response.status(200).send({ sendit });
}
});
This should look similar to your code, I'm using async/await
instead of getting into a promise soup of a nightmare.
The code is running on this endpoint https://us-central1-geofirestore-tests.cloudfunctions.net/chooseCity if you want to test it, it's just looking for a POST
request with a application/json
content type. Hopefully this helps!
Here's a sample request:
var request = require('request');
var options = {
'method': 'POST',
'url': 'https://us-central1-geofirestore-tests.cloudfunctions.net/chooseCity',
'headers': {
'Content-Type': 'application/json'
},
body: JSON.stringify({"distance":100,"location":[1,3]})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
It should return the following:
{
"sendit": [
{
"exists": true,
"id": "GtfRlw86OYRTawCmeBG1",
"data": {
"coordinates": {
"_latitude": 1,
"_longitude": 3
}
},
"distance": 0
},
{
"exists": true,
"id": "OSttNfDZgaF8G1MzsSG4",
"data": {
"coordinates": {
"_latitude": 1,
"_longitude": 3
}
},
"distance": 0
},
{
"exists": true,
"id": "dkk6QoHfojPdORitrFHn",
"data": {
"coordinates": {
"_latitude": 1,
"_longitude": 3
}
},
"distance": 0
},
{
"exists": true,
"id": "krtqVQurpQnMXdPlA9MG",
"data": {
"coordinates": {
"_latitude": 1,
"_longitude": 3
}
},
"distance": 0
},
{
"exists": true,
"id": "q01xXMOXLDkQiezUohnU",
"data": {
"coordinates": {
"_latitude": 1,
"_longitude": 3
}
},
"distance": 0
}
]
}
Updated this one last time to modify the sendit
bit to call the doc data.
I'm trying to update firebase config for react-redux-firebase v3 & redux-firestore to test my functions I used a month ago before closing. Could also be an issue with using the same bucket I was messing about in with a websocket server... But I digress since you got a response & it works, we don't have to wait for anymore than the day so far to close this. Thanks for the work on this Michael, good job
Michael,
It works, but Can you also write a single request instead of the querySnapshot for us?
My reason: I am sure I’m not updating the geofirestore data every time I pan on the map, and the cloud function only runs when user changes city. I even made the variable radius static in the user-triggered function to test, but it still writes to the console every bit of panning on the map. Thank you!
This is a single request, at least my sample. It uses the .get()
method which returns a single query in the form of a Promise.
Hi Michael or community This is a question to help others implement, and myself. No bug, of course. [I've edited this with improvements I am sure of to keep short... getting closer...]
Anyway, here is a Google Cloud Function, It works until the query, req.body is fine with CORS I have one item but can't get it from query when the res.send() is sent [still working on this, no error is helpful yet, now testing how far down compiles...] [now getting {"sendit":{"domain":{"domain":null,"_events":{},"_eventsCount":1,"members":[]}}}]
[Tried this]
[Instead of this]
[End]
adding document, the geofirestore way, in a redux action