MichaelSolati / geofirestore-js

Location-based querying and filtering using Firebase Firestore.
https://geofirestore.com
MIT License
505 stars 58 forks source link

Problem With Query #102

Closed VesperDev closed 5 years ago

VesperDev commented 5 years ago

Hello my friends, i have a doubt

Have a code for get the result in my collection, but ever ever i have empty data, i write radius 0 and i have 2 results ¿why?

"geofirestore": "^3.0.2"

    let db = firebase.firestore()
    const geoFirestore: GeoFirestore = new GeoFirestore(db)

    geoFirestore.collection('talleres')
        .near({ center: new firebase.firestore.GeoPoint(latitude, longitude), radius: 30 })
        .onSnapshot((snapshot) => {
            console.log(snapshot)
    })

Captura de Pantalla 2019-04-26 a la(s) 0 49 38

Captura de Pantalla 2019-04-26 a la(s) 0 58 55

MichaelSolati commented 5 years ago

@VesperDev I'm sorry I'm having difficulty understanding your question. Could you elaborate, or maybe share an example (like on stackblitz)

VesperDev commented 5 years ago

Yes, of course, basically placing the radius 0 I get results but if I write radio 30 the results do not appear :(

without results geoFirestore.collection('talleres') .near({ center: new firebase.firestore.GeoPoint(latitude, longitude),radius : 30 })

with results geoFirestore.collection('talleres') .near({ center: new firebase.firestore.GeoPoint(latitude, longitude),radius : 0 })

MichaelSolati commented 5 years ago

Ok, so I finally took a look at it and from what I can gather (just code skimming) before I was doing a check like this...

if (this._center && this._radius) {

If the radius was set to 0 then it was treated as false and there wouldn't be a geoquery. What I'm going to change it is to this:

if (this._center && typeof this._radius !== 'undefined') {

Which should pass if 0 is inputted and give a geoquery of a 0 radius.

VesperDev commented 5 years ago

Thanks my friends let my check

MichaelSolati commented 5 years ago

You should be able to run npm i geofirestore/geofirestore-js#dev to test it.

MichaelSolati commented 5 years ago

Geofirestore version 3.3.1 is going through CI and will be autodeployed to NPM. That should take care of this issue. Enjoy!

michelemangiacotti commented 5 years ago

I've the same problem, any solution?

MichaelSolati commented 5 years ago

@michelemangiacotti what version are you using?

michelemangiacotti commented 5 years ago

My version is ; "geofirestore": "^3.3.1".

MichaelSolati commented 5 years ago

Ok, so I've created a somewhat simple example that works here => https://stackblitz.com/edit/typescript-sa8wdv

Line 50 is the query and the snapshot, and the structure of the docs looks like this:

Screen Shot 2019-07-29 at 3 34 27 PM

If it's not working and your code looks like the stackblitz, it's likely a data structure issue.

michelemangiacotti commented 5 years ago

Hi, thank you for the quickly response, I've try your solution but it doesn't work for me. I've this firestore data structure : immagine I would like to load from my table "items" only elements that are into a range of my approximate position. My code is very similar to yours, I've added your solution too. immagine

I don't understand if there is a misunderstanding, because you make the call function "near" on a list already loaded from the database, Could you tell me if I'm having the wrong approach?

MichaelSolati commented 5 years ago

Ah, that second near is the actually query, the first one is just to populate the database incase there are less than 10 documents. But looking at your data structure, is see the l field is embedded in the address when it needs to be in the root of the document. I also don't see a g field which is also necessary. Please review the required data structure for geofirestore here.

michelemangiacotti commented 5 years ago

Ah, now I understand, thank you, but "l" is a field not included in "address" is just a graphic effect that makes it look like that, one last question: the structure of my "items" must be composed exactly by only the 3 fields : g: string; l: GeoPoint; d: DocumentData; or can I have additional fields as I showed you in the previous answer?

MichaelSolati commented 5 years ago

@michelemangiacotti well the idea is that at the top level geofirestore uses the data and everything in the d level is your data. While you can have things on the top level, it'll get funky and is not recommended.

michelemangiacotti commented 5 years ago

Hello Michael, I tried to play a simple example with your proposed fire structure and I have a strange behavior, the elements are loaded only when the radian is above 4000, my elements are all 20-30 meters from my current location, and especially are loaded by the query always all elements, I tried to insert an element very far away as position but is loaded the same by the query. This is my structure, the call is the one you sent me a while ago. Would you know how to help me?

image

MichaelSolati commented 5 years ago

@michelemangiacotti your g field only has a degree of precision of 3, so your g field (the geohash), ideally you'd want to go to 10 degrees of precision (otherwise it'll be very far from the origin). Also that geohash is not a valid geohash... You'd expect srb0bzyd6p for those coordinates...

michelemangiacotti commented 5 years ago

I'm sorry Michele this thing had escaped me, at this point I can ask you how to generate a geohash for coordinates, I'm doing some tests memorizing by hand some examples of records, could you tell me what I have to call to generate a test structure that has a valid geohash based on coordinates? Is there something integrated in geoFireStore? Thanks for the quick answer!

MichaelSolati commented 5 years ago

@michelemangiacotti I have a library called geokit which you can pass in a LatLng literal in order to create a geohash => https://www.npmjs.com/package/geokit#geokithashcoordinates-latlngliteral-precision-number-string

Or you could just use geofirestore and add documents with it.

michelemangiacotti commented 5 years ago

Thank you @MichaelSolati your are a boss, it work!

michelemangiacotti commented 5 years ago

Hello @MichaelSolati , I would like to know if you can add a condition where to the call:

geofirestore.collection('items').where("d.myField", "==", true).near({ center: new firebase.firestore.GeoPoint(latitude, longitude), radius: 10, })

I have the following error:

Error getting documents: [FirebaseError: The query requires an index.

on which fields should I create the firestore index: d.myField and ?

MichaelSolati commented 5 years ago

See #137

hindsricardo commented 5 years ago

Looks like the issue is still persisting. v3.3.1 only works when the radius is set to 0

MichaelSolati commented 5 years ago

@hindsricardo can you explain your issue in more detail?

hindsricardo commented 5 years ago

@MichaelSolati v3.3.1 only works when the radius is set to 0

Here is my code is firebase cloud functions:

const {GeoFirestore} = require('geofirestore');

const database = admin.firestore(); const geofirestore = new GeoFirestore(database); const Geo = geofirestore.collection('profile');

exports.initialLocationSearch = functions.https.onRequest((req, res) => { let body = req.body; let parseBody = JSON.parse(body);

// Create a GeoQuery based on a location console.log(body, parseBody.radius, parseBody.lat, parseBody.long)

const query = Geo.near({ center: new admin.firestore.GeoPoint(parseBody.lat, parseBody.long), radius: parseBody.radius }).limit(100);

query.get().then((value) => { res.status(200).send(value._docs.map((x) => { x._data = x.data(); return x; })); });

})

I checked the library code and it looks like the fixed you mentioned below is actually in place.

if (this._center && typeof this._radius !== 'undefined') {

Any suggestions. This is the last feature preventing me from finishing my app.

MichaelSolati commented 5 years ago

_docs isn't a valid attribute or property of a geosnapshot, just use docs also can you provide a stackblitz example? Without access to the database I couldn't test this.

Another possible issue is that the database structure is invalid. A screenshot from the firebase console could be helpful.

Here's an app example with a query and radius which does work => https://stackblitz.com/edit/geofirestore-distance