Backendless Support
 

Search data objects by distance from a location

One of the benefits of the Backendless data-to-geo relationships is search by distance. That means Backendless can search for data objects using the location of the related geopoints. 

Consider an example from a taxi-reservation system. 

There may be several cabs-for-hire in the area. An app needs to locate all available cars within the specified distance from where the customer is located. 

The class representing a cab may look like this:

package com.mbaas.sample;
import com.backendless.geo.GeoPoint;
public class Car
{
 public String make;
 public String model;
 public boolean available;
 public GeoPoint location;
}

NOTICE: the class has the location field of type GeoPoint. The related GeoPoint object represents the current location of the car.

To search for all available cars within distance from a location (which is the place where the customer who needs to get a car is located), Backendless provides a special function which can be used in the SQL queries. The following SQL where clause can be used in Backendless to find all available cars located within 10 miles from the specified coordinates (32.803, -96.770 - near Dallas, Texas downtown):
distance( 32.803, -96.770, location.latitude, location.longitude ) < mi(5) and available = true
The query when sent to the Car  table should be read in plain English as: "locate all available cars for which the location.latitude and location.longitude coordinates are located within 5 miles from the point at 32.803, -96.770."

Notice the location.latitude  and location.longitude arguments. The "location" part refers to the location field of the Car class shown above. The "latitude" and "longitude" parts refer to the properties of the GeoPoint class identified by the location field. The mi(5) operator is used by the distance function and indicates the distance of 5 miles. 

The code to setup some sample data is:

Car car1 = new Car();
car1.make = "Toyota";
car1.model = "Prius";
car1.available = true;
car1.location = new GeoPoint( 32.800755, -96.816140 );
Car car2 = new Car();
car2.make = "Kia";
car2.model = "Sorento";
car2.available = true;
car2.location = new GeoPoint( 32.778892, -96.781465 );
Car car3 = new Car();
car3.make = "Toyota";
car3.model = "Camry";
car3.available = false;
car3.location = new GeoPoint( 32.770304, -96.796056 );
Backendless.Data.of( Car.class ).save( car1 );
Backendless.Data.of( Car.class ).save( car2 );
Backendless.Data.of( Car.class ).save( car3 );
The sample code below demonstrates the query in action:

Asynchronous API sample (Android and Plain Java): 

double myLatitude = 32.779108;
double myLongitude = -96.797000;
String query = "distance( %f, %f, location.latitude, location.longitude ) < mi(5) and available = true";
String whereClause = String.format( query, myLatitude, myLongitude );
BackendlessDataQuery dataQuery = new BackendlessDataQuery( whereClause );
QueryOptions queryOptions = new QueryOptions();
queryOptions.addRelated( "location" );
dataQuery.setQueryOptions( queryOptions );
Backendless.Data.of( Car.class ).find( dataQuery, new AsyncCallback<BackendlessCollection<Car>>()
{
 @Override
 public void handleResponse( BackendlessCollection<Car> cars )
 {
 if( cars.getCurrentPage().size() == 0 )
 System.out.println( "Did not find any cars" );
 Iterator<Car> iterator = cars.getCurrentPage().iterator();
 while( iterator.hasNext() )
 {
 Car car = iterator.next();
 System.out.println( String.format( "Found car: %s %s", car.make, car.model ) );
 }
 }
 @Override
 public void handleFault( BackendlessFault backendlessFault )
 {
 System.out.println( "Server reported an error - " + backendlessFault.getMessage() );
 }
} );
Synchronous API sample (Plain Java only):
double myLatitude = 32.779108;
double myLongitude = -96.797000;
String query = "distance( %f, %f, location.latitude, location.longitude ) < mi(5) and available = true";
String whereClause = String.format( query, myLatitude, myLongitude );
BackendlessDataQuery dataQuery = new BackendlessDataQuery( whereClause );
QueryOptions queryOptions = new QueryOptions();
queryOptions.addRelated( "location" );
dataQuery.setQueryOptions( queryOptions );
BackendlessCollection<Car> cars = Backendless.Data.of( Car.class ).find( dataQuery );
if( cars.getCurrentPage().size() == 0 )
 System.out.println( "Did not find any cars" );
Iterator<Car> iterator = cars.getCurrentPage().iterator();
while( iterator.hasNext() )
{
 Car car = iterator.next();
 System.out.println( String.format( "Found car: %s %s", car.make, car.model ) );
}
Program output:
Found car: Toyota Prius
Found car: Toyota Camry
Is article helpful?