androidgoogle-cloud-firestoregeofirestore

GeoFirestore: getAtLocation not returning the full list of documents


GeoFirestore has at least two methods for returning the documents in Firestore.

getAtLocation() and geoFirestore.queryAtLocation(new GeoPoint(lati, longi), radi).addGeoQueryDataEventListener()

According to the documentation, getAtLocation() will return to the SingleGeoQueryDataEventCallback a list of all the documents presents in the area and an exception if something goes wrong.

Below is how I am doing the queries:

        if (!lat.getText().toString().isEmpty()) {
            lati = Double.parseDouble(lat.getText().toString());
            longi = Double.parseDouble(lon.getText().toString());
        }

        double radi = Double.parseDouble(rad.getText().toString());
        Log.i(TAG, "onClick: radius is "+radi);

        geoFirestore.getAtLocation(new GeoPoint(lati, longi), radi, new GeoFirestore.SingleGeoQueryDataEventCallback() {
            @Override
            public void onComplete(@Nullable List<? extends DocumentSnapshot> list, @Nullable Exception e) {
                //Log.i(TAG, "GeoFirestore: onComplete");
                if (e != null) {
                    Log.i(TAG, "GeoFirestore: onComplete: error");
                    return;
                } else {
                    Log.i(TAG, "GeoFirestore: onComplete: list.size() is "+list.size());
                    for (DocumentSnapshot documentSnapshot : list) {
                        Log.i(TAG, "GeoFirestore: onComplete: documentSnapshot is "+documentSnapshot);
                    }
                }
            }
        });

        geoQuery = geoFirestore.queryAtLocation(new GeoPoint(lati, longi), radi);

        geoQuery.addGeoQueryDataEventListener(new GeoQueryDataEventListener() {
            @Override
            public void onDocumentEntered(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
                Log.i(TAG, "onDocumentEntered: addGeoQueryDataEventListener - documentSnapshot is "+documentSnapshot);
            }

            @Override
            public void onDocumentExited(@NotNull DocumentSnapshot documentSnapshot) {
                Log.i(TAG, "onDocumentExited: addGeoQueryDataEventListener - documentSnapshot is "+documentSnapshot);
            }

            @Override
            public void onDocumentMoved(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
                Log.i(TAG, "onDocumentMoved: addGeoQueryDataEventListener - documentSnapshot is "+documentSnapshot);
            }

            @Override
            public void onDocumentChanged(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
                Log.i(TAG, "onDocumentChanged: addGeoQueryDataEventListener - documentSnapshot is "+documentSnapshot);
            }

            @Override
            public void onGeoQueryReady() {
                Log.i(TAG, "onGeoQueryReady: addGeoQueryDataEventListener");
            }

            @Override
            public void onGeoQueryError(@NotNull Exception e) {
                Log.i(TAG, "onGeoQueryError: addGeoQueryDataEventListener");
            }
        });

And below is the result of both queries:

debinf FirebaseAct: onClick: radius is 10.0
debinf FirebaseAct: onDocumentEntered: addGeoQueryDataEventListener - documentSnapshot is DocumentSnapshot{key=Stores/P7FfBlnChxqkjABsONSo, metadata=SnapshotMetadata{hasPendingWrites=false, isFromCache=false}, doc=Document{key=Stores/P7FfBlnChxqkjABsONSo, data=ArraySortedMap{(address=>av. fernandes lima, s/n - farol), (city=>maceio), (g=>7nq96cb3e3), (id=>222222222), (image=>http://walmart), (l=>GeoPoint { latitude=-9.614147, longitude=-35.738036 }), (name=>walmart), (opening=>ArraySortedMap{(fri=>07:00-23:59), (mon=>07:00-23:59), (sat=>07:00-22:00), (sun=>07:00-18:00), (thu=>07:00-23:59), (tue=>07:00-23:59), (wed=>07:00-23:59)};), (phone=>), (state=>alagoas)};, version=SnapshotVersion(seconds=1574434563, nanos=920733000), documentState=SYNCED}}
debinf FirebaseAct: onDocumentEntered: addGeoQueryDataEventListener - documentSnapshot is DocumentSnapshot{key=Stores/iKIZ9n54jpnThvNx0Prw, metadata=SnapshotMetadata{hasPendingWrites=false, isFromCache=false}, doc=Document{key=Stores/iKIZ9n54jpnThvNx0Prw, data=ArraySortedMap{(address=>avenida maceio, s/n - Tabuleiro), (city=>maceio), (g=>7nq96p934s), (id=>333333333), (image=>http://gbarbosa), (l=>GeoPoint { latitude=-9.58262891, longitude=-35.76965511 }), (name=>GBarbosa), (opening=>ArraySortedMap{(fri=>07:00-21:00), (mon=>07:00-21:00), (sat=>07:00-21:00), (sun=>07:00-18:00), (thu=>07:00-21:00), (tue=>07:00-21:00), (wed=>07:00-21:00)};), (phone=>), (state=>alagoas)};, version=SnapshotVersion(seconds=1574445438, nanos=550840000), documentState=SYNCED}}
debinf FirebaseAct: onDocumentEntered: addGeoQueryDataEventListener - documentSnapshot is DocumentSnapshot{key=Stores/8HU4UdSLNEaCg5eqeZbq, metadata=SnapshotMetadata{hasPendingWrites=false, isFromCache=false}, doc=Document{key=Stores/8HU4UdSLNEaCg5eqeZbq, data=ArraySortedMap{(address=>avenida vereador dario marsiglia, s/n - cleto marques luz), (city=>maceio), (g=>7nq9d32m26), (id=>123456789), (image=>http://tim), (l=>GeoPoint { latitude=-9.57229704, longitude=-35.76013863 }), (name=>Lider), (opening=>ArraySortedMap{(fri=>07:00-23:59), (mon=>07:00-23:59), (sat=>07:00-23:59), (sun=>07:00-23:59), (thu=>07:00-23:59), (tue=>07:00-23:59), (wed=>07:00-23:59)};), (phone=>ddd xxxx-yyyy), (state=>alagoas)};, version=SnapshotVersion(seconds=1574444945, nanos=558590000), documentState=SYNCED}}
debinf FirebaseAct: onGeoQueryReady: addGeoQueryDataEventListener
debinf FirebaseAct: GeoFirestore: onComplete: list.size() is 1
debinf FirebaseAct: GeoFirestore: onComplete: documentSnapshot is DocumentSnapshot{key=Stores/P7FfBlnChxqkjABsONSo, metadata=SnapshotMetadata{hasPendingWrites=false, isFromCache=false}, doc=Document{key=Stores/P7FfBlnChxqkjABsONSo, data=ArraySortedMap{(address=>av. fernandes lima, s/n - farol), (city=>maceio), (g=>7nq96cb3e3), (id=>222222222), (image=>http://walmart), (l=>GeoPoint { latitude=-9.614147, longitude=-35.738036 }), (name=>walmart), (opening=>ArraySortedMap{(fri=>07:00-23:59), (mon=>07:00-23:59), (sat=>07:00-22:00), (sun=>07:00-18:00), (thu=>07:00-23:59), (tue=>07:00-23:59), (wed=>07:00-23:59)};), (phone=>), (state=>alagoas)};, version=SnapshotVersion(seconds=1574434563, nanos=920733000), documentState=SYNCED}}

How to make getAtLocation() return a list of documents just like addGeoQueryDataEventListener()?


Solution

  • As of version v1.5.0, there is a discrepancy between the code and the documentation. The documentation states that queryAtLocation uses kilometers:

    // creates a new query around [37.7832, -122.4056] with a radius of 0.6 kilometers
    val geoQuery = geoFirestore.queryAtLocation(GeoPoint(37.7832, -122.4056), 0.6)
    

    However, the code converts from meters to latitude:

    fun distanceToLatitudeDegrees(distance: Double) = distance / Constants.METERS_PER_DEGREE_LATITUDE
    

    There is an open issue on Github.

    Passing meters to the queryAtLocation should solve the problem.