Search data by distance from a location not working

Hi. I am trying to retrieve some objects using what is suggested here https://backendless.com/feature-103-search-data-objects-by-distance-from-a-location. This is my code:

double myLatitude = 40.416754;
double myLongitude = -3.703891;
String query = "distance( %f, %f, location.latitude, location.longitude ) < km(" + DEFAULT_RADIUS_SEARCH_KM + ")";
String whereClause = String.format(query, myLatitude, myLongitude);


BackendlessDataQuery dataQuery = new BackendlessDataQuery(whereClause);
QueryOptions queryOptions = new QueryOptions();
queryOptions.addRelated("location");
queryOptions.addRelated("images");
dataQuery.setQueryOptions(queryOptions);


Backendless.Data.of(Place.class).find(dataQuery, new AsyncCallback&lt;BackendlessCollection&lt;Place&gt;>() {
    @Override
    public void handleResponse(BackendlessCollection&lt;Place&gt; places) {
        callback.onSuccess(places.getCurrentPage());
    }


    @Override
    public void handleFault(BackendlessFault backendlessFault) {
        callback.onError(new Exception(backendlessFault.getMessage()));
    }
});

WHERE DEFAULT_RADIUS_SEARCH_KM = 1, but I am not getting the results sorted by distance. I am always getting the same order in results no matter which origin geopoint I use.

Andrés,

We are looking into it.

Regards,
Mark

Hi Mark.

Do you have any update?

Thanks,
Andrés

Hi Andres,

We researched this issue. Changing the current implementation so that the result is sorted automatically was quite difficult. We came up with a following workaround: when you run a geo search in radius, results (geopoints) will be returned sorted. Since geopoints can have related data objects in the metadata, it would allow the same level of functionality as what you originally asked about.

There is a bit of work we need to do to get this done, but it would be a lot more realistic on our side.

What do you think?

Regards,
Mark

Hi Mark.

In your approach, I must have all the information that is currently in my data tables as metadata in geolocation, and I also will lose all the benefits of using data tables. Besides, it doesn’t feel like the right way to handle data. I thought one of the main reasons to use geoqueries in data tables would be to get sorted results …

No, that is not true. A geopoint may have one metadata property which points to a data object. There is no reason to duplicate all the object properties in the metadata. More details are in the doc:

http://backendless.com/documentation/geo/rest/geo_relations_with_data_objects.htm

Hi Mark.

I have checked the documentation and you are absolutely right, it is possible to relate a geopoint to an object through metadata and the search is working. This is my code:

BackendlessGeoQuery geoQuery = new BackendlessGeoQuery();
geoQuery.setLatitude(myLatitude);
geoQuery.setLongitude(myLongitude);
geoQuery.setRadius(Double.valueOf(DEFAULT_RADIUS_SEARCH_KM));
geoQuery.setUnits(Units.KILOMETERS);
geoQuery.setCategories(Arrays.asList("Leisure", "Churchs"));
geoQuery.setIncludeMeta(true);
Backendless.Geo.getPoints(geoQuery, new AsyncCallback&lt;BackendlessCollection&lt;GeoPoint&gt;>() {
    @Override
    public void handleResponse(BackendlessCollection&lt;GeoPoint&gt; response) {
        List&lt;GeoPoint&gt; points = response.getCurrentPage();
        for (int i = 0; i < points.size(); i++) {
            GeoPoint point = points.get(i);
            //Object object = point.getMetadata("place"); //how to retrieve this as a custom object?
            System.out.println(place.getName());
        }
    }


    @Override
    public void handleFault(BackendlessFault fault) {
        callback.onError(new Exception(mContext.getString(R.string.error_places_found)));
    }
});

I am able to retrieve the geopoints, but I have two doubts:

  1. I don’t how to retrieve the metadata property that points to my object already casted as a custom object. In this case, is called “place”. In the metadata, it is a HashMap. Is there an utility in Backendless Android SDK that could map from HashMap t the custom class? An example in the Android SDK would be extremely helpful for me in this case.

  2. If I don’t specify any categories in the geoquery, it doesn’t get any results. Is there a way to set the geoquery to search in all existing categories?

Thanks,
Andrés

Hi Andrés,

Try calling the following method before you run the search:

Backendless.Persistence.mapTableToClass( tableName, clientSideClass )

As for your second question, the categories collection (or at least one of them) are required.

Regards,
Mark

Thanks Mark.

About my second question, I think it would be useful to search in all categories. Is it something you may consider to include in the future?

I have another doubt. If my metadata custom object has a one-to-one or one-to-many relation with another object, is there a way to set the geoquery to retrieve that relation too?

Thanks,
Andrés

Hi Andrés,

There is an API call to get a list of all categories:
http://backendless.com/documentation/geo/android/geo_retrieving_geo_categories.htm

If you use that call first and pass the complete list in the search API, it would do what you want. However, from the performance perspective, it may not be the best approach - it an expensive call.

As for loading the relations, you can use the auto-load option:
https://backendless.com/feature-21-loading-related-data-objects-the-auto-load-approach/

Regards,
Mark

For loading the relations, is there a way to do it without autoload?

Yes, there is::

https://backendless.com/feature-28-loading-related-data-objects-the-semi-lazy-approach/