0

Im using firebase, and I want to retrieve the users that have a specific address coordinates.

For that Im using this method

 showPopUpInfo(longitude:any, latitude:any){
    return this.afs.collection('Utilizador',ref=>ref.where('morada.Coordenadas.latitude', '==', latitude).where('morada.Coordenadas.longitude', '==' , longitude)).get()
}

the values of variables latitude and longitude are:

longitude : -8.364

latitude : 41.237

My firebase "Utilizador" document:

enter image description here

the ouput of the query is:

enter image description here

In my opinion the user is not found because, in spite of the values of latitude and longitude are the same the precison of latitude and longitude are different, but I dont know how to solve this problem

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Pugnatore
  • 395
  • 3
  • 19

2 Answers2

1

Actually, the document's values for latitude and longitude are stored as strings, as shown in this screenshot. You can tell because they have quotes around them. If you hover the mouse over that field, you will also see "(string)" to the right.

If you're using number values in your query, the query will never match this document, because Firebase does not consider any number to be equal to any string.

If your query is actually using the exact same strings, you will come up with a match. But storing numbers as strings is generally not recommended, as you will lose the ability to correctly perform range queries over those number values, since strings sort differently than numbers.

One point of advice - don't use the TypeScript type any in your function. Be specific, and accept only string or number, as required by the query. This will help raise errors in your code if you're passing something of the wrong type.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • I tried to put the values as numbers in the document but still not working – Pugnatore Jan 08 '20 at 19:33
  • You're probably having a hard time getting two exact floating point numbers. This is kind of a difficult problem to solve because of the way IEEE floating point numbers are represented with very high precision. In fact, you have a whole different problem now than the one you started with, and it kind of deserves its own question. If you really have to query for precise GPS coordinates (which is maybe not a good idea to begin with), you might have to not store floating point numbers at all, and instead require integers with the exact precision needed. – Doug Stevenson Jan 08 '20 at 19:40
  • So if I understood well what you are suggesting is to define the precision that I want when I store the coordinates in the database right? – Pugnatore Jan 08 '20 at 19:43
  • You can't define the precision of an IEEE floating point number, but you can say how many digits you want in an integer. Try multiplying the lat/lon by 1,000,000, dropping the decimals, then using the exact integer values for the query. – Doug Stevenson Jan 08 '20 at 20:20
  • But queries for exact lat/lon pairs is very uncommon (how does one come up with these exact numbers for the query??), and I think you should consider what Frank is saying in the other answer about using ranges with geohashes. – Doug Stevenson Jan 08 '20 at 20:22
1

The more typical approach to find objects at a certain location is to use geo-queries based on ranges. With a small enough range, you can exactly the result you want. Unfortunately such geoqueries are not built into Firestore at the moment.

And since Firestore can queries can only contain range filter on a single field, you can't do longitude and latitude with that directly. Instead most developer use a solution that is built on top of that, based on Geohashes. Geohashes combine latitude and longitude into a single (alphanumerical) value that can be filtered on ranges.

To learn more about running geoqueries on Firestore, I'd recommend watching the video of my talk on the topic. But definitely also check out these other questions where the topic of geoquerying on Firestore is covered:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807