1

I am using Parse.com with my iPhone app.

I ran into a problem earlier where I was trying to add the currently logged in user to another user's PFRelation key/column called "friendsRelation" which is basically the friends list.

The only problem, is that you are not allowed to save changes to any other users besides the one that is currently logged in.

I then learned, that there is a workaround you can use, using the "master key" with Parse Cloud Code.

I ended up adding the code here to my Parse Cloud Code: https://stackoverflow.com/a/18651564/3344977

This works great and I can successfully test this and add an NSString to a string column/key in the Parse database.

However, I do not know how to modify the Parse Cloud Code to let me add a user to another user's PFRelation column/key.

I have been trying everything for the past 2 hours with the above Parse Cloud Code I linked to and could not get anything to work, and then I realized that my problem is with the actual cloud code, not with how I'm trying to use it in xcode, because like I said I can get it to successfully add an NSString object for testing purposes.

My problem is that I do not know javascript and don't understand the syntax, so I don't know how to change the Cloud Code which is written in javascript.

I need to edit the Parse Cloud Code that I linked to above, which I will also paste below at the end of this question, so that I can add the currently logged in PFUser object to another user's PFRelation key/column.

The code that I would use to do this in objective-c would be:

[friendsRelation addObject:user];

So I am pretty sure it is the same as just adding an object to an array, but like I said I don't know how to modify the Parse Cloud Code because it's in javascript.

Here is the Parse Cloud Code:

Parse.Cloud.define('editUser', function(request, response) {
    var userId = request.params.userId,
        newColText = request.params.newColText;

    var User = Parse.Object.extend('_User'),
        user = new User({ objectId: userId });

    user.set('new_col', newColText);

    Parse.Cloud.useMasterKey();
    user.save().then(function(user) {
        response.success(user);
    }, function(error) {
        response.error(error)
    });
});

And then here is how I would use it in xcode using objective-c:

[PFCloud callFunction:@"editUser" withParameters:@{
    @"userId": @"someuseridhere",
    @"newColText": @"new text!"
}];

Now it just needs to be modified for adding the current PFUser to another user's PFRelation column/key, which I am pretty sure is technically just adding an object to an array.

This should be fairly simple for someone familiar with javascript, so I really appreciate the help.

Thank you.

Community
  • 1
  • 1
user3344977
  • 3,584
  • 4
  • 32
  • 88

1 Answers1

3

I would recommend that you rethink your data model, and extract the followings out of the user table. When you plan a data model, especially for a NoSQL database, you should think about your queries first and plan your structure around that. This is especially true for mobile applications, as server connections are costly and often introduces latency issues if your app performs lots of connections.

Storing followings in the user class makes it easy to find who a person is following. But how would you solve the task of finding all users who follow YOU? You would have to check all users if you are in their followings relation. That would not be an efficient query, and it does not scale well.

When planning a social application, you should build for scalabilty. I don't know what kind of social app you are building, but imagine if the app went ballistic and became a rapidly growing success. If you didn't build for scalability, it would quickly fall apart, and you stood the chance of losing everything because the app suddenly became sluggish and therefore unusable (people have almost zero tolerance for waiting on mobile apps).

Forget all previous prioities about consistency and normalization, and design for scalability.

For storing followings and followers, use a separate "table" (Parse class) for each of those two. For each user, store an array of all usernames (or their objectId) they follow. Do the same for followers. This means that when YOU choose to follow someone, TWO tables need to be updated: you add the other user's username to the array of who you follow (in the followings table), and you also add YOUR username to the array of the other user's followers table.

Using this method, getting a list of followers and followings is extremely fast.

Have a look at this example implementation of Twitter for the Cassandra NoSQL database: https://github.com/twissandra/twissandra

Marius Waldal
  • 9,537
  • 4
  • 30
  • 44
  • Hi. Many thanks for this, really helped me designing my system. However, I am not sure I understand the need for having 2 tables for followers, and followings. Since you store the other person's username/objectId in the relevant array, what is the point of the 2 tables at all ? Can you please illustrate this ? – Petar Jun 14 '14 at 17:13
  • 1
    I am not sure I understand your question, but remember that every person has both followers and follow other people. When I follow you, the app needs to quickly get a list of me and all the other followers, so you need 1 record that contains an array of all the followers. However, when the app needs to display the users YOU are following, we can't scan all the followers-records and track the ones where YOU are included (that would not scale). To quickly lookup the people you follow, you need your own record in the followings table, with an array of all the people you follow. – Marius Waldal Jun 26 '14 at 11:14
  • 1
    Remember that even though you COULD get the same result by doing it the other way, this would not be designing for queries. This is especially important when developing for mobile devices. – Marius Waldal Jun 26 '14 at 11:17
  • I've given it a lot of thought lately, and I definitely think my last question makes no sense now :D Its an interesting problem and keeping followers and followings separate is a very nice solution. I wonder if there are other ways that this could be achieved though ? For example, as a requirement I have at the moment: upon 2 users following each other - a special must be performed. – Petar Jun 26 '14 at 15:52
  • @Handsomeguy, I think pe60t0's model is fine. Based on their question, it seems they are creating a friend relation, not a followers/followed relation. In a friend relation, two users who are friends would by default follow each other, there is no wiggle room (ie a situation where one user follows another but is not followed back). Given my interpretation is correct, wouldn't this approach be fine? Wouldn't it be just one query to get your list of friends? If I am missing something, could you please elaborate on your solution, cause I am in the same position with my app – yaboi Sep 07 '15 at 07:50
  • @yaboi Yes, getting a list of the people I follow is easy as pie: you add every new following to the list of followings (or friends). But if you are following me, I'm on your list. And on the list of maybe hundreds or thousands of other people who follow me. How can I easily get a list of those who follow me using this model? You would have to check every friendlist to see if my name is on it... – Marius Waldal Sep 23 '15 at 19:41
  • What if each user had a followers and following column, both of which were kept up to date. Then when user A follows user B, user A would be put in user B's followers list. And user B would be put in user A's following list – yaboi Sep 24 '15 at 05:41
  • @yaboi Exactly, but that was my original suggestion in the answer... ;-) – Marius Waldal Oct 09 '15 at 08:07