Skip to content

Relations with Data Objects

Backendless Data Service manages application's data objects and provides APIs to work with data objects. Backendless provides integration between data objects managed by Data Service and geo points managed by Geo Service for the scenarios when a logical connection between the two types must exist in an application. For instance, in a taxi ordering app a data object may represent a taxi car, while a geo point represents its location on the map. It is logical to link the two together so they can be retrieved and managed at once.

The Geo-to-Data integration is implemented through geo point metadata. A metadata property may reference one or more data objects. These relations may be created using the API or with Backendless Console. Once a relation is established, the console displays it in the Metadata column as a link to related data object(s). When a geo point is retrieved using the API, any related data objects can be retrieved by using the same principle for loading geo point metadata. The geo-to-data relation is bidirectoral, that is, a data object may reference a geo point through object properties (table columns). You can learn more about it in the Relations with Geo Points  section of the Data documentation.

Apart from linking with the data objects, you can also link a geo point with a user object. Establishing relations with a user objects is performed the same way as with a data object.

Establishing Relations with a Data Object via Console

To link a geo point with a data object:

  1. Click the Geolocation icon to open the Geo location screen.
  2. Select a geo category to get a list of geo points from it.
  3. Click the plus icon for a geo point you want to link with a data object.
    geofence-screen10.zoom50
  4. The Add Related Object pop-up window will display.
  5. Type in a metadata property name in the Property field. This is the name of a new metadata property which will point to a related data object:
    geofence-screen11.zoom70
  6. Select a data table from from the Table drop-down menu. If you want to establish relation with a user object, select the Users  table from the drop-down menu. A list of the data objects which belong to the selected table will display.
  7. Select the check-boxes for the data object(s) you want to link the geo point with.
  8. Click the Add Related Objects button to establish a relation and save the changes.

Once a relation is established, the name of the property and the related data table name will display for the geo point:

geofence-screen12.zoom50

Updating/Deleting Relations

You can update or delete a geo to data relation by following the same process as above. The only difference is in order to access the"relation management" popup click the yellow box identifying the relation:

Create a Geo to Data Relation with the API

Creating a relationship between a geo point and data objects uses the same API as saving a geo point with metadata. The data object referenced in the metadata is saved in a table in the Data Service storage.

The example below adds a geo point representing a location of a taxi cab. The geo point includes the "TaxiCab" metadata property which references an object from the TaxiCab data table. This is an example of a one-to-one relation (one geo point is related to one data object).

First, declare the TaxiCab class:

@interface TaxiCab : NSObject

@property (strong, nonatomic) NSString *objectId;
@property (strong, nonatomic) NSString *carmake;
@property (strong, nonatomic) NSString *carmodel;

@end
@objcMembers class TaxiCab: NSObject {
    var objectId: String?
    var carmake: String?
    var carmodel: String?
}

To create a one-to-one relation

TaxiCab *taxi = [TaxiCab new];
taxi.carmake = @"Toyota";
taxi.carmodel = @"Prius";

DataStoreFactory *dataStore = [Backendless.shared.data of:[TaxiCab class]];
[dataStore saveWithEntity:taxi responseHandler:^(TaxiCab *savedTaxi) {
    GeoPoint *geoPoint = [[GeoPoint alloc] initWithLatitude:40.7148 longitude:-74.0059 categories:@[@"taxi"] metadata:@{@"service_area": @"NYC"}];
    [Backendless.shared.geo saveGeoPointWithGeoPoint:geoPoint responseHandler:^(GeoPoint *savedGeoPoint) {
        // link one point to data object
        [dataStore setRelationWithColumnName:@"location:GeoPoint:1" parentObjectId:savedTaxi.objectId childrenObjectIds:@[savedGeoPoint.objectId] responseHandler:^(NSNumber *relatons) {
            NSLog(@"Relation has been set");
        } errorHandler:^(Fault *fault) {
            NSLog(@"Error: %@", fault.message);
        }];
    } errorHandler:^(Fault *fault) {
        NSLog(@"Error: %@", fault.message);
    }];
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
let taxi = TaxiCab()
taxi.carmake = "Toyota"
taxi.carmodel = "Prius"

let dataStore = Backendless.shared.data.of(TaxiCab.self)
dataStore.save(entity: taxi, responseHandler: { savedTaxi in
    let geoPoint = GeoPoint(latitude: 40.7148, longitude: -74.0059, categories: ["taxi"], metadata: ["service_area": "NYC"])
    Backendless.shared.geo.saveGeoPoint(geoPoint: geoPoint, responseHandler: { savedGeoPoint in
        // link one point to data object
        if let savedTaxi = savedTaxi as? TaxiCab,
            let taxiId = savedTaxi.objectId,
            let savedGeoPointId = savedGeoPoint.objectId {
            dataStore.setRelation(columnName: "location:GeoPoint:1", parentObjectId: taxiId, childrenObjectIds: [savedGeoPointId], responseHandler: { relations in
                print("Relation has been set")
            }, errorHandler: { fault in
                print("Error: \(fault.message ?? "")")
            })
        }
    }, errorHandler: { fault in
        print("Error: \(fault.message ?? "")")
    })
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

To create a one-to-many relation

TaxiCab *taxi = [TaxiCab new];
taxi.carmake = @"Toyota";
taxi.carmodel = @"Prius";

DataStoreFactory *dataStore = [Backendless.shared.data of:[TaxiCab class]];
[dataStore saveWithEntity:taxi responseHandler:^(TaxiCab *savedTaxi) {
    GeoPoint *droppOff1 = [[GeoPoint alloc] initWithLatitude:40.757977 longitude:-73.98557 categories:@[@"DropOffs"] metadata:@{@"name": @"Times Square"}];
    [Backendless.shared.geo saveGeoPointWithGeoPoint:droppOff1 responseHandler:^(GeoPoint *savedDroppOff1) {
        GeoPoint *droppOff2 = [[GeoPoint alloc] initWithLatitude:40.748379 longitude:-73.98557 categories:@[@"DropOffs"] metadata:@{@"name": @"Empire State Building"}];
        [Backendless.shared.geo saveGeoPointWithGeoPoint:droppOff2 responseHandler:^(GeoPoint *savedDroppOff2) {
            // link several points to data object
            [dataStore setRelationWithColumnName:@"DropOffs:GeoPoint:n" parentObjectId:savedTaxi.objectId childrenObjectIds:@[savedDroppOff1.objectId, savedDroppOff2.objectId] responseHandler:^(NSNumber *relations) {
                NSLog(@"%@ relations have been set", relations);
            } errorHandler:^(Fault *fault) {
                NSLog(@"Error: %@", fault.message);
            }];
        } errorHandler:^(Fault *fault) {
            NSLog(@"Error: %@", fault.message);
        }];
    } errorHandler:^(Fault *fault) {
        NSLog(@"Error: %@", fault.message);
    }];        
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
let taxi = TaxiCab()
taxi.carmake = "Toyota"
taxi.carmodel = "Prius"

let dataStore = Backendless.shared.data.of(TaxiCab.self)
dataStore.save(entity: taxi, responseHandler: { savedTaxi in
    let droppOff1 = GeoPoint(latitude: 40.757977, longitude: -73.98557, categories: ["DropOffs"], metadata: ["name": "Times Square"])
    Backendless.shared.geo.saveGeoPoint(geoPoint: droppOff1, responseHandler: { savedDroppOff1 in
        let droppOff2 = GeoPoint(latitude: 40.748379, longitude: -73.985565, categories: ["DropOffs"], metadata: ["name": "Empire State Building"])
        Backendless.shared.geo.saveGeoPoint(geoPoint: droppOff2, responseHandler: { savedDroppOff2 in
            // link several points to data object
            if let savedTaxi = savedTaxi as? TaxiCab,
                let taxiId = savedTaxi.objectId,
                let savedDroppOff1Id = savedDroppOff1.objectId,
                let savedDroppOff2Id = savedDroppOff1.objectId {
                dataStore.setRelation(columnName: "DropOffs:GeoPoint:n", parentObjectId: taxiId, childrenObjectIds: [savedDroppOff1Id, savedDroppOff2Id], responseHandler: { relations in
                    print("\(relations) relations have been set")
                }, errorHandler: { fault in
                    print("Error: \(fault.message ?? "")")
                })
            }
        }, errorHandler: { fault in
            print("Error: \(fault.message ?? "")")
        })
    }, errorHandler: { fault in
        print("Error: \(fault.message ?? "")")
    })            
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})