How-To Use Pointers/Relations - Parse.com JavaScript SDK
<dl>
Pre-Note: This is aimed at the JavaScript SDK of Parse, however it may help if you are using a different SDK like Android. So if you are having issues with Relations/Pointers give this a read!
</dl>
Edit: @tyaramis sparked a great question of how to do multi-dimensional querying in Parse, so I made another protip dedicated to his question: https://coderwall.com/p/-uzbrq/multi-dimensional-querying-parse-com-javascript-sdk
When I first started to use Parse I was tasked with creating a database for our first rendition of our mobile application for DD buddy. We knew what information we needed/wanted at the time, the trick was to set up an efficient database that didn't repeat information. Coming from a MySQL background and knowing nothing other than PHPMyAdmin, I was fully aware of relationships between database tables, or in Parse's case, Classes. However, I did not understand how I would set up a relationship between classes in Parse.
When I started to dive into Parse's JS SDK Documentation I found the sections on Relationships. The documentation does a great job on describing the situations you would want to use a Pointer, an Array (of either Pointers or Relations), a Relation, or a Join Table. What it lacks though is a specific FULL example of how to query these pointers in order to receive useful information. It is actually quite simple, and you will realize the enormous benefits of using pointers/relations by the time this article is done!
Before I start, please do not take any of this as me saying the documentation Parse supplies is lacking. If you dive into their specific SDK documentation it all is laid out in a very easy to understand manner, and some of it just takes time and messing around with to understand. This just happens to be one sections that I had issues implementing due to lack of information.
Class Structures
First let's set up three Classes in Parse. Users, Posts and Comments.
_User Structure:
- objectId
- username
- password
- name - string
Posts Structure:
- objectId
- postName - string
- postMsg - string
- postAuthor - Pointer< _User > (Pointer to the User Class)
Comments Structure:
- objectId
- msg - string
- post - Pointer< Posts > (Pointer to the Posts Class)
- user - Pointer< _User > (Pointer to User Class)
Now, let's get all the posts in the Posts class and find out the name of the user that is its author.
var Posts = Parse.Object.extend("Posts");
var query = new Parse.Query(Posts);
What we just did is set up a query for our JavaScript code to talk to our Posts class.
query.include("postAuthor");
This line of code is what allows us to get the information from the user entry to postAuthor
is "pointing" to without doing another query.
query.find().then(function(results){
/* Go Through Each Post */
var postsArray = new Array();
for(i in results){
/* Set obj to current post*/
var obj = results[i];
/* Get Post's Name */
var postName = obj.get("postName");
/* Get Post's Message */
var postMsg = obj.get("postMsg");
/* Get Post Author's Name */
var authorName = obj.get("postAuthor").get("name");
/* Let's Put the Post Information in an Array as an Object*/
postsArray.push({
post:{
name: postName,
msg: postMsg
},
author: authorName
});
}
})
Then all we did there was, using the query we created, gather all of the posts and put their info in an object inside the postsArray
.
However, if you look at where we declared authorName
you can see how we got the user's/author's name. When you use the .include()
method on your query you can then use .get()
on the column you included, and then another .get()
to get the column you wish of the class the pointer is pointing to. (E.g. postAuthor
is the column we included and name
is the column we want on the User class. So we can do, obj.get("postAuthor").get("name")
and we'll receive back the name of the user.)
Multi-Dimensional Includes
In some cases you might need to go further than just including one pointer. Say you are including a pointer, and on the entry you're pointing to, it has another pointer and you need the info the second level pointer is pointing to. How do we do that? Well, let's gather all the comments in the Comments class, and then we'll try to get the post author name (not the name of who commented).
Same first steps, we'll query the Comments class this time.
var Comments= Parse.Object.extend("Comments");
var query = new Parse.Query(Comments);
Next, we'll do another include. First we'll include the post
column in the Comments class, because we might want to know what the post was that this comment is on. Then, we'll do another include in order to have access to the postAuthor
, we will be using dot notation in order to access multi-dimensional pointers. If we just wanted the postAuthor
we could leave out the first include, but in this example let's get both.
/*Get the Post's Info*/
query.include("post");
/*Get the Post Author's Info*/
query.include("post.postAuthor");
/*Get the Comment's Author Info*/
query.include("user");
To recap the last include, we use dot notation to include the pointer that in on the postAuthor
column of the Posts class that we are accessing from the post
column of the Comments class. Then we just query for the information like we did on the Posts.
query.find().then(function(results){
/* Go Through Each Comment*/
var commentsArray = new Array();
for(i in results){
/* Set obj to current comment*/
var obj = results[i];
/* Get Post's Name */
var postName = obj.get("post").get("postName");
/* Get Post's Message */
var postMsg = obj.get("post").get("postMsg");
/* Get Post Author's Name */
var authorName = obj.get("post").get("postAuthor").get("name");
/* Get Comment's Message */
var commentMsg = obj.get("msg");
/* Get Comment's Author*/
var commentAuthor = obj.get("user").get("name");
/* Let's Put the Comment Information in an Array as an Object*/
commentsArray.push({
post:{
name: postName,
msg: postMsg
},
author: authorName,
comment: {
author: commentAuthor,
msg: commentMsg
}
});
}
})
So that wraps it up, we covered both standard including for pointers and multi-dimensional includes. If you have any questions, please let me know and I'll try my best to help!
Cheers!
Zach
Written by Zach Case
Related protips
10 Responses
Hi.
How can I set the query for a column of pointer class?
For example I would like to query the posts based on the postAuthor country.
This does not work:
var Posts = Parse.Object.extend("Posts");
var query = new Parse.Query(Posts);
query.include("postAuthor");
query.equalTo("postAuthor.country", selectedCountry);
Thanks for your answer in advance.
@tyaramis Great question! To be honest, I haven't messed with a query like that. (At least I can't remember doing so.) So before I give you an answer I will mess around to try and accomplish what you want, and I'll get back to you! Sorry for the delay in answering this, Halloween weekend was a no work weekend, haha.
Cheers brotha!
Edit: https://coderwall.com/p/-uzbrq/multi-dimensional-querying-parse-com-javascript-sdk
@tyaramis - I figured out how to do what you are desiring. However, it would be a rather lengthy post so I am going to create a tip for it and tag you in it, I'll also come back here and leave the link when it is up.
Cheers!
Saved my day! Thank you :)
I take this code but It not work.. what data I need to make it work
hey buddy, in all docs peoples are talk about getting a parent from child (one to many relation) like getting post details from comments.But i want vise versa, i have list of posts and a 'post title' ,and i want all the comments for that particular post(uses title for identify particular post) how can i achieve this?
Dude, these articles are super super useful (especially for a new developer)! Thanks for doing this man.
Hey Zach,
So quick question on Pointers - can you point to another object in the same class?
Specifically, my app has multi-level navigation and I'm trying to determine whether I have to create a separate class for each level category, or can lump them into one class and have a key that states which category-level it is.
Hello and very nice job!
I have one question. Lets say that we are on the multiquery example and i have extended the Comments class and i also get the posts with this comment.
How can i make the query of the printed comments to be on an descending order BUT not from Comments class, i want to get a descending order from Posts class!
I mean to make a query in Comments, but the order should be from the Posts.
Any idea?
damn saved my day <3 created an account just to say thanks :D