Does backendless.userService have a relations functions?

good morning…

I want what ever I can have quite frankly… What I mean is when I check the autoLoad on the column ‘usersSaleItems’ in the ‘backendlessUser’ class which has a relation to the ‘usersItems’ class, what does it actually give me?

Does it just give me the objectId’s of the objects or does it give me the actual objects? either way how do I do this using the userService as in the API Docs I only see a relation function for GEOpoints? I can find no way to add-in queryOptions and have the userService ‘find’ with ‘queryOptions’.

I can for say another class using the ‘persistenceService’ it gives me all options but not the same as ‘userService’ API.

ok, I just did below but I still don’t really know what it gave me, usable anyway…

Here is the code:

Fault *fault = nil;

BackendlessDataQuery *query = [BackendlessDataQuery new];

QueryOptions *queryOptions = [QueryOptions new];

queryOptions.related = [NSMutableArray arrayWithArray:@[@"usersSaleItems", @"usersSaleItems.saleItems"]];

query.queryOptions = queryOptions;

BackendlessCollection *saleItemCollection = [backendless.persistenceService find:[BackendlessUser class] dataQuery:query error:&fault];



NSLog(@"HERE IS THE COLLECTION: %@",saleItemCollection);

here is the output:

<It gave me the BackendlessUser class objects then>
), query: <BackendlessDataQuery> -> properties: (null), whereClause: (null), queryOptions: <QueryOptions> -> {

offset = 0;

pageSize = 100;

related =     (

    usersSaleItems,

    "usersSaleItems.saleItems"

);

}

Hi Steve,

Here is ViewController.swift from my test project:



import UIKit


class Address : NSObject {
    
    var street : NSString?
    var city: NSString?
    var state : NSString?
}


class ViewController: UIViewController {


    let backendless = Backendless.sharedInstance()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
               
        //registerUserSync()
        loginUser()
    }
    
    func registerUserSync() {
        
        Types.tryblock({ () -> Void in
            
            let address = Address()
            address.street = "123 Main St"
            address.city = "Dallas"
            address.state = "Texas"
            
            let user = BackendlessUser()
            user.email = "spiday@backendless.com"
            user.password = "greeng0blin"
            user.setProperty("address", object: address)
            
            let registeredUser = self.backendless.userService.registering(user)
            print("User has been registered: \(registeredUser)")
            },
            
            catchblock: { (exception) -> Void in
                print("Server reported an error: \(exception as! Fault)")
            }
        )
    }


    func loginUser() {
        
        Types.tryblock({ () -> Void in
            
            let registeredUser = self.backendless.userService.login("spiday@backendless.com", password: "greeng0blin")
            print("User has been logged in (SYNC): \(registeredUser)")
            let address = self.backendless.userService.currentUser.getProperty("address") as! Address
            print("Autoloded Address object is in currentUser: \(address.street), \(address.city), \(address.state)")
            
            self.backendless.userService.logout()
            },
            
            catchblock: { (exception) -> Void in
                print("Server reported an error: \(exception as! Fault)")
        })
    }


}


First, I uncommented line 19 and commented line 20, then built and run my app, and got this result (sorry, but you need to click on another bookmark, Users for example, then return to Data bookmark - and you will see a new 1:1 ‘address’ relation in your Users table):
http://support.backendless.com/public/attachments/29f4b3344f29fb3e54f95d45c98dd429.png&lt;/img&gt;

I switched on the ‘autoload’ checkbox for 1:1 ‘address’ relation, then I commented line 19 and uncommented line 20, built and run my app, and got this result in a log:
http://support.backendless.com/public/attachments/f8ad87b745cc641cf4b0436f58d6a48d.png&lt;/img&gt;
So, due to checked ‘autoload’ checkbox my currentUser object has whole Address object in its ‘address’ property (1:1 relation)

Hope this example will helpful for you.

Regards,
Slava

You can change this code with 1:N relation user property, for example

Here is my example - with 1:N relation in user property, it works fine for me:

    
    func registerUserSync() {
        
        Types.tryblock({ () -> Void in
            
            let address1 = Address()
            address1.street = "123 Main St"
            address1.city = "Dallas"
            address1.state = "Texas"
            
            let address2 = Address()
            address2.street = "17 Brooklin"
            address2.city = "NY"
            address2.state = "NY"
           
            let user = BackendlessUser()
            user.email = "spiday@backendless.com"
            user.password = "greeng0blin"
            user.setProperty("address", object: [address1, address2])
            
            let registeredUser = self.backendless.userService.registering(user)
            print("User has been registered: \(registeredUser)")
            },
            
            catchblock: { (exception) -> Void in
                print("Server reported an error: \(exception as! Fault)")
            }
        )
    }


    func loginUser() {
        
        Types.tryblock({ () -> Void in
            
            let registeredUser = self.backendless.userService.login("spiday@backendless.com", password: "greeng0blin")
            print("User has been logged in (SYNC): \(registeredUser)")
            let addresses = self.backendless.userService.currentUser.getProperty("address") as! [Address]
            for address in addresses {
                print("Autoloded Address object is in currentUser: \(address.street), \(address.city), \(address.state)")
            }
            
            self.backendless.userService.logout()
            },
            
            catchblock: { (exception) -> Void in
                print("Server reported an error: \(exception as! Fault)")
        })
    }

and result:
http://support.backendless.com/public/attachments/007d2b03459ac4184fe73682956046d1.png&lt;/img&gt;

ok… I just spending time with this now but I haven’t exposed myself to Swift so I will attempt to translate as best I can.

This scenario also works for me (in context of example with 1:N relation user property below in this thread):

 
 func singleStepRetrieval() {
 
 let dataQuery = BackendlessDataQuery()
 let queryOptions = QueryOptions()
 queryOptions.related = ["address"];
 dataQuery.queryOptions = queryOptions
 
 var error: Fault?
 let bc = backendless.data.of(BackendlessUser.ofClass()).find(dataQuery, fault: &error)
 if error == nil {
 print("Users have been found: \(bc.data)")
 let users = bc.data as! [BackendlessUser]
 for user in users {
 let addresses = user.getProperty("address") as! [Address]
 for address in addresses {
 print("'\(user.email) user address object is: \(address.street), \(address.city), \(address.state)")
 }
 
 }
 }
 else {
 print("Server reported an error: \(error)")
 }
 
 }

and result:
http://support.backendless.com/public/attachments/421976ff143502b417f6d719d9f7be0e.png&lt;/img&gt;

right I am sooooo lost its crazy now…

i run this:

BackendlessUser *user = backendless.userService.currentUser;

BackendlessUser *updatedUser = [backendless.userService update:user];



NSLog(@"USER PROPERTIES: %@",updatedUser);

and i get this:

created = “2016-02-17 12:34:24 +0000”;
deliveryAddress = "276 Badminton road \nDownend\nBristol “;
email = "autismsdad@gmail.com”;
lastLogin = “2016-02-18 09:44:23 +0000”;
name = 230804953926880;
objectId = “D0C17A4F-DBB1-4424-FF8C-07D2C5A2C200”;
ownerId = “<null>”;
pandaPoundsAV = 50;
pandaPoundsRSV = 0;
password = “<null>”;
saleItems = “<null>”;
telephoneNumber = 07748482531;
updated = “2016-02-18 09:44:27 +0000”;
url = “https://scontent.xx.fbcdn.net/hprofile-xta1/v/t1.0-1/s200x200/11094799_147956635545046_9161749565228965248_n.jpg?oh=939cf08fad48f835f1bf6db834dcab5d&oe=575B63A0”;
“user-token” = “F08B629D-F2FC-D2D9-FF4F-0DE0BF79BB00”;
usersSaleItems = (
“<saleItems: 0x7fa6e3d4d2a0>”

);

now I get ‘usersSaleItems’ = ("<saleItems: 0x7fa6e3d4d2a0>") which is cool, however! What is it!? Is it an NSObject a dictionary an array or simply is it the objectId of the linked item therefore I need to run a dataQuery method to get it?

Either way what is the line of code I need to write to extract this information. this is what I can’t seem to see…

Ok more testing…

I sudden realised that the one-to-many relations wasn’t working when I was only seeing 1 object in the ‘usersSaleItems’ results. When I looked at the data base GUI I realised that only the latest object was holding the link. Am I missing a line of code here?

So here are the screen shots:
http://support.backendless.com/public/attachments/b4fef71b2ff7340301e37fae27f250bd.png&lt;/img&gt;

http://support.backendless.com/public/attachments/9b032911decd62e72fe2d584f8382eb0.png&lt;/img&gt;
and here is the code for saving the object:

saleItems *saleItemUpload = [saleItems new];

saleItemUpload.itemTitle = itemTitle.text;

saleItemUpload.itemDescription = descriptionUITextView.text;

saleItemUpload.itemURLA = itemURLA;

saleItemUpload.itemURLB = itemURLB;

NSNumber *number;

number = @([pandaPoundsValue.text intValue]);

saleItemUpload.itemPPCost = number;

BackendlessUser *user = backendless.userService.currentUser;

[user setProperty:@“usersSaleItems” object: saleItemUpload];

user = [backendless.userService update:user];

Steve, in your code you have set saleItemUpload object of ‘saleItems’ class as “usersSaleItems” user property:

[user setProperty:@“usersSaleItems” object: saleItemUpload];
i.e. you create 1:1 relation, so
saleItems *item = [user getProperty:@“usersSaleItems” ];
you will get item object of ‘saleItems’ class, and you can use this object and its properties.
The rule working with user property: “what you have set, than you will get”.

If you need 1:N relation - you need:
[user setProperty:@“usersSaleItems” object: @[saleItemUpload]];
then:
NSArray<saleItems*> *items = [user getProperty:@“usersSaleItems” ];

I think it is easy sense.

Ok I have decided to go with a straight call to the saleItems class directly which is giving me a collection of the objects.

Last question (we hope) is I get the collection which is type BackendlessCollection but how do I extract the objects from the collection?

I tried the change you say for 1:N but I get the same result. Still the newest object grabs the relation.

Investigate this examples:

Maybe all samples in this github - GitHub - Backendless/BlogFeatureDay-iOS - will be helpful for you, there are obj-c & swift targets in each project.

thanks I will investigate

Consider the penny has well and truly dropped!

I am now able to extract all the information from the collection so, once again a BIG thanks to you all.

I know I have said it before but:
Backendless Support verse Parse Support ----- There is no competition! Backendless wins hands down! in fact your support is super amazing and really responsive and I WISH I found Backendless before I even tied myself with Parse, I really do.

Have a great day!

Yes, getPage: method of BackendlessCollection class returns BackendlessCollection object - see BackendlessCollection.h file: https://github.com/Backendless/ios-SDK/blob/master/SDK/lib/backendless/include/BackendlessCollection.h

If you need to get array which is contained in BackendlessCollection object, you can use its method:
-(NSArray *)getCurrentPage;
So, for your purpose:
NSArray *arrayOfCollection = [[collection getPage:1] getCurrentPage];
or, in a context of your sample, simply:

NSArray *arrayOfCollection = [collection getCurrentPage];

I’ve given the link to BackendlessCollection paging example above.