Best way to retrieve a sorted list of nested relationships

Hello, i have a 1:N relation between the table Users and Users (used for friend relation); every user has a 1:N relation with table Posts that contains all the users’ posts. Now i want to get a sorted (creation date) list of my friends’ posts. Which is the best way to obtain this “list”? I have tried to do this in my code, retrieving, in a for cycle, for each friend, all the posts (in a big unsorted list). I think that this approach is too expensive in terms of app’s performance.

My code:

List<BackendlessUser> friends = 


new ArrayList (Arrays.asList((BackendlessUser[]) mCurrentUser.getProperty("Friends")));



for(BackendlessUser elem : friends){
    print += "Friends Name: " + elem.getProperty("name") + ":\n";

    List<Posts> uPosts = new ArrayList<>(Arrays.asList((Posts[]) elem.getProperty("Posts")));


for(Posts p : uPosts){

        print += "Post status: " + p.getStatus();
        print += "Post date: " + p.getCreated().toString();


    }

}

I’d go a complete different approach, called the ACL way.

The key is to restrict access to “find” objects of table “Post”, so that only friends are allowed to " find" a users post.

So,whenever you befriend to someone you’ll addyourself to a Table, the users friends. When he creates a New object of type Post, he will allowall his friends to find this object. (This can be done asynchronously with handlers, after save)

Now that you would only be allowed to find those post objects of your friends you don’t even have to query anything. Just request all data from Table post sorted AS you wish, that’s it.

Thank you for your reply; i work with Edilio. I will take your approach into consideration but i have a doubt: do i need to create a new Table? Because, to establish that two Users are friends, i use only the Users table.
Furthermore, by the “getProperty” method, can i get directly a sorted List? Or do i have to sort it?

Hi Pierfabio,

Are you talking about a sorted list of friends or a sorted list of Posts?

Regards,
Mark

Hi Mark,
i’m talking about a sorted list of Posts. With the auto-load enabled to the column posts in the Users table, i’m able to get a List of Posts with this code (cUser is the current user):

Backendless.Data.mapTableToClass("Post",Post.class);
List<Post> posts = new ArrayList(Arrays.asList((Post[])cUser.getProperty("posts")));

but this List isn’t sorted. It’s possible to retrieve directly a sorted List? Without sorting algorithms in code. Or i need to use BackendlessDataQuery with QueryOptions (removing the auto-load)?
Sorry for bad english,
Regards, Pierfabio

If you use auto-load the result is not sorted. Using auto-load is not a good idea as may impact the performance of your app. A better approach would be:

    Determine the collection of user's friends, specifically get their objectId's Run a query against the Posts table to load all the posts which belong to the objectId collection from (1). This query can use the sorting option in BackendlessDataQuery.
Regards, Mark

Hi Mark,
at the moment i do not consider the friends relationship.
I have tried with the Single Step Retrieval and the Two Step Retrieval reading the articles of the restaurant (my target is to get a sorted List). I post my code (Two Step Retrieval):

Backendless.Data.mapTableToClass("Post", Post.class);
BackendlessCollection<BackendlessUser> collection = Backendless.Data.of(BackendlessUser.class).find();
Iterator<BackendlessUser> iterator = collection.getCurrentPage().iterator();
while (iterator.hasNext()) {
BackendlessUser user = iterator.next();
List<String> relations = new ArrayList<String>();
relations.add("posts");
Backendless.Data.of(BackendlessUser.class).loadRelations(user, relations);
printLocations(Arrays.asList((Post[]) user.getProperty("posts")));
}

the method printLocations is the same of the restauran article.
In line 9 i need to use the getProperty to obtain an unsorted List (in Single step / Two step is the same).
Now i have 2 problems:

  1. if a user does not have posts, the method getProperty returns an array of Object (ClassCastException [Ljava.lang.Object; cannot be cast to [Lcom.pierf.Post;)
  2. if a user has a lot of posts, i can call the “printLocations” method without exceptions but i can’t sort the list with QueryOptions.

i have also tried with the “Loading with Relations Depth”. It works fine with this code (i can use QueryOptions without problems):

BackendlessDataQuery query = new BackendlessDataQuery();
query.setWhereClause("Users[posts].objectId = '" + cUser.getObjectId() + "'");
QueryOptions queryOptions = new QueryOptions("text");
query.setQueryOptions(queryOptions);
BackendlessCollection<Post> collection = Backendless.Data.of(Post.class).find(query);
for(Post p : collection.getData()) {
System.out.println(p.getText());
}

What is the best choiche between these approaches?

Sorry for bad english.
Regards,
Pierfabio

Pierfabio,

I would go with this approach:

BackendlessDataQuery query = new BackendlessDataQuery();
query.setWhereClause("Users[posts].objectId = '" + cUser.getObjectId() +"'");
QueryOptions queryOptions = new QueryOptions("text");
query.setQueryOptions(queryOptions);
BackendlessCollection<Post> collection = Backendless.Data.of(Post.class).find(query);
for(Post p : collection.getData()) {
System.out.println(p.getText());
}

The reason I’d use this is because you can configure sorting options in QueryOptions using the addSortByOption method.

Thank you very much from my team, all works perfectly.

Best regards,
Edilio

Hi Mark,

i’ve got a problem with the sorted List of friends’ posts.

    Determine the collection of user's friends, specifically get their objectId's Run a query against the Posts table to load all the posts which belong to the objectId collection from (1). This query can use the sorting option in BackendlessDataQuery.
for the first point i have write this code to get a Collection of user's friends
BackendlessDataQuery query = new BackendlessDataQuery();
query.setWhereClause("Users[to].objectId = '" + cUser.getObjectId() + "'");
BackendlessCollection<BackendlessUser> friends = Backendless.Data.of(BackendlessUser.class).find(query);

How can i write the query for the point 2? I want a single List of all friend’s posts sorted by “created”.

Regards,
Pierfabio

Hi Pierfabio,

Now that you have a collection of friends, do the following:

    Iterate over the "friends" collection (friends.getCurrentPage().iterator()) Create a whereClause that looks like this: Users[posts].objectId in ('fiend1ObjectId', 'friend2ObjectId',...) Run a query against the Post table with a query from (2)
Regards, Mark

Hi Mark,
all works perfectly! I did not know that i could use “in”.
Thank you very much
Best regards,
Pierfabio