2

I'm building out a little app and the first thing I need to do is make a call to Parse's REST API using AngularJS's ngResource.

I've successfully constructed two Parse classes (let's call them "Parent" and "Child" for now) and set up a many-to-many relation between them such that a Parent can relate to zero-n Child objects and a Child may relate to zero-n Parent objects.

So far, the very basic stuff works fine. This method, for example, successfully retrieves all the Parent objects:

.factory('Parent', function($resource, appConfig) {
  return $resource('https://api.parse.com/1/classes/Parent/:id', {}, {
    list : {
      method : 'GET',
      headers: appConfig.parseHttpsHeaders
    }
  });
})

Awesome. It even has a "Child" attribute describing the relation (as you would expect) but does not return the actual Child objects inside each Parent.

Now I need to expand on this method to retrieve the related Child objects at the same time - I really don't want to have to make another call per Parent to get the related Child objects.

So we try this:

.factory('Parent', function($resource, appConfig) {
  return $resource('https://api.parse.com/1/classes/Parent/:id', {}, {
    list : {
      method : 'GET',
      headers: appConfig.parseHttpsHeaders,
      params : {
        'include' : 'Child'
      }
    }
  });
})

...and the server returns...the exact same response as before. The Child records are not included.

Any ideas where I'm going wrong?

Edit: Note that while I've set up the Parent and Child relation already, I'm open to suggestions if this is not the best way of doing things if I need to query the data in this way. There will be a limited set of Parent objects (let's say under 100) and a much smaller set of possible Child objects (under 30).

slashwhatever
  • 732
  • 8
  • 24
  • Does the API provide the possibility to expand related objects? – a better oliver Feb 27 '15 at 10:56
  • Have you checked the class level permissions of the child class? 'include' will take that into account and might not return any objects if the security settings for 'Child' disallow get/find. Would be worth checking that – Björn Kaiser Feb 27 '15 at 12:06
  • Thanks for the input so far. To address those two points: 1. yes. https://parse.com/docs/rest#objects-retrieving "When retrieving objects that have pointers to children, you can fetch child objects by using the include option." 2. all objects are set to allow read/write/get/find – slashwhatever Feb 27 '15 at 13:54

2 Answers2

0

The problem is the distinction between pointers and relations. Pointers can be eagerly fetched using include, but relations cannot. If the cardinality of the parent->child relationship is low, use an array of pointers instead of a relation and you'll get the results you expect/desire.

danh
  • 62,181
  • 10
  • 95
  • 136
  • OK, that makes sense. What's missing is that Parse.com's docs don't tell you how to create that relationship structure in JS – slashwhatever Mar 01 '15 at 21:19
  • Its a little bit hidden partly because pointers are easy to use. See the short discussion here (https://www.parse.com/docs/js_guide#objects-pointers). For your parent->child relation, declare an array on the parent and use the add() and remove() methods on PFObject to add/remove a child. When you later query the parent, just say .include("children") and they'll be eagerly fetched. (You can also say things like .equalTo("children", someChild) in order to fetch a parent whose children array contains someChild). – danh Mar 02 '15 at 00:29
  • The link you mention says for many-to-many relationships: "Many-to-many relationships are modeled using Parse.Relation." Which is what I had been doing before. In the JS SDK there's no mention of using Arrays or Pointers for many-to-many. – slashwhatever Mar 02 '15 at 09:33
  • CRACKED IT!!!! Will post an update to answer the OP myself. Thanks for the help danh :) – slashwhatever Mar 02 '15 at 09:48
-1

With help from danh, I've worked out how to get this set up in the way I wanted. Here's a little code snippet:

var cId = 'CHILD_ID';
var pId = 'PARENT_ID';

var Child = Parse.Object.extend("child");
var cQ = new Parse.Query(Child);

var Parent = Parse.Object.extend("parent");
var pQ = new Parse.Query(Parent);

pQ.get(pId, {
    success: function (mResponse) {
        console.log(pResponse);
        cQ.get(cId, {
            success: function (cResponse) {
                console.log(cResponse);
                pResponse.add('children', cResponse);
                pResponse.save();

            },
            error: function (object, error) {
                // The object was not retrieved successfully.
                // error is a Parse.Error with an error code and message.
            }
        });
    },
    error: function (object, error) {
        // The object was not retrieved successfully.
        // error is a Parse.Error with an error code and message.
    }
});

First of all, create your two classes in the Parse.com data browser. Ensure that the Parent class has an Array column defined (in this case it was called 'children').

Add your parent object id and child object id to the relevant variables in the script and run it (obviously including your API keys at the top of the script). Hey presto! You will have an array of pointers for each relationship you run the script for.

Not only that, I can confirm that my AngularJS REST Api call returns the parent and child details in one call.

slashwhatever
  • 732
  • 8
  • 24
  • So you are no longer using Parse.com's actual relation association? Instead you are using the array at the data-type? http://stackoverflow.com/questions/29989835/parse-com-restful-one-to-many-request-with-related-children-populated – techie.brandon May 01 '15 at 15:35