I have two parse classes; Companies and Ratings. It is a one to many relationship. Companies can have many Ratings. This is the statement I would perform in SQL:
SELECT Companies.name, Ratings.rating
FROM Companies
INNER JOIN Ratings
ON Ratings.name_id = Companies.name_id
ORDER BY Companies.name
I want the equivalent of this in Parse, but I'm not sure of how to go about it. Here is what I've currently tried:
function getRatings() {
var tableA = new Parse.Query(Companies);
var tableB = new Parse.Query(Ratings);
tableB.equalTo("name_id", tableA.name_id);
tableB.find({
success: function(results) {
$scope.$apply(function() {
$scope.companies = results.map(function(obj) {
return {
id: obj.get("name_id"),
name: obj.get(tableA.name),
rating: obj.get("rating"),
parseObject: obj
};
});
});
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
I am calling this function when the controller loads. This code displays the rating in my output, but not the name of the company.
I am trying to get all the companies listed in the companies object, then pair them with all the ratings they have in the ratings object. Their common key is name_id. This is the code I am using within my Angular view:
<div class="span12">
<div ng-repeat="company in companies | filter: query | orderBy: orderList"
class="well company-description">
<h1>{{company.name}}</h1>
<h3>Rating: {{company.rating}}</h3>
</div>
</div>
If I am way off base on this, please let me know
Get rid of the name_id column in the Ratings class. This isn't how you're supposed to define relationship using Parse.
There are a couple of options for you to choose.
Option 1
Using the Parse data browser, add a new column under the Companies class, called ratings. It should be a column of type Relation and point to Ratings as the target class. (Let me know if you need more information on how to do this.)
Then, when you create or edit a company, add ratings as follows:
var Companies = Parse.Object.extend("Companies");
var Ratings = Parse.Object.extend("Ratings");
var company = new Companies({name: "Some Company"});
company.relation("ratings").add(new Ratings({stars: 5}));
company.save();
Then, when querying Companies, do so as follows:
new Parse.Query(Companies).find({
success: function(companies) {
for (var i = 0; i < companies.length; i++) {
companies[i].relation("ratings").query().find({
success: function(ratings) {
// Finally, I have the ratings for this company
}
}
}
}
});
Option 2
Using the Parse data browser, add a new column under the Companies class, called ratings. It should be a column of type Array.
Then, when you create or edit a company, add ratings as follows:
var Companies = Parse.Object.extend("Companies");
var Ratings = Parse.Object.extend("Ratings");
var company = new Companies({
name: "Some Company",
ratings: [new Ratings({stars: 5})]
});
company.save();
Then, when querying Companies, do so as follows:
new Parse.Query(Companies).include("ratings").find({
success: function(companies) {
// Yay, I have access to ratings via companies[0].get("ratings")
}
});
include("ratings") tells Parse to include the actual objects, rather than pointers to objects for the given key.
Conclusion
Option 1 is better if you are expecting to have a large amount of ratings for each company, and if you don't always plan on retrieving all the ratings each time you query the companies.
Option 2 is better if the number of ratings for each company is relatively small, and you always want ratings to come back when you query companies.
I found out how to resolve the Uncaught You can't add an unsaved Parse.Object to a relation. error.
var addRating = new Ratings({stars: rating}); // save rating first, then associate it with a company
addRating.save({
success: function() {
var addCompany = new Companies({name: name});
addCompany.relation("ratings").add(addRating);
addCompany.save();
}
});
The rating has to be saved first, then the company relation can be added later on... makes sense, but took me awhile to figure it out! :S