Proper procedure Relationship Mapping with primary key and initial sync

774 views
Skip to first unread message

Bob Spryn

unread,
Feb 8, 2012, 6:01:58 PM2/8/12
to RestKit
So I'm trying to put together the proper procedure for doing
relationship mapping with keys instead of embedding the objects in the
json, as the embedding piece is really hammering our API and timeouts
are occurring.

I was looking at this other thread:
http://groups.google.com/group/restkit/browse_thread/thread/b30075024bf69531/399297fe81707575?lnk=gst&q=map+relationship+using+id#399297fe81707575

Is there some documentation or an example somewhere of the exact
correct way to do this?

My followup question is this: Once my mapping with id's is working,
how should I perform an initial sync to pull down all the data? How
does this work when objects may be pointing via id relationship to
other objects that don't yet exist in core data? Is it going to make
an individual http request in the middle of a large request for a
singular object because of the relationship, or will it somehow batch
all these together?

Best,
Bob

Bob Spryn

unread,
Feb 9, 2012, 3:32:49 PM2/9/12
to RestKit
Hmmm. Is everybody embedding the full objects in the json? Anyone
using primary key ids instead?

On Feb 8, 4:01 pm, Bob Spryn <bobsp...@gmail.com> wrote:
> So I'm trying to put together the proper procedure for doing
> relationship mapping with keys instead of embedding the objects in the
> json, as the embedding piece is really hammering our API and timeouts
> are occurring.
>
> I was looking at this other thread:http://groups.google.com/group/restkit/browse_thread/thread/b30075024...

Bob Spryn

unread,
Feb 10, 2012, 12:59:51 AM2/10/12
to RestKit
As a follow-up, how does one do one-to-many with ids? Does an array of
ids just work?

Pedro Anisio Silva

unread,
Feb 10, 2012, 2:40:02 PM2/10/12
to RestKit
I would to like to see this happening. In my first implementation I
inserted all objects inside my json response. But it would be nice to
use only the ID to make an resource "talk" to another.




Pedro

Bob Spryn

unread,
Feb 13, 2012, 12:16:09 AM2/13/12
to RestKit
Bumping this as I'm sort of spinning my wheels until I figure this
out.

On Feb 8, 4:01 pm, Bob Spryn <bobsp...@gmail.com> wrote:
> So I'm trying to put together the proper procedure for doing
> relationship mapping with keys instead of embedding the objects in the
> json, as the embedding piece is really hammering our API and timeouts
> are occurring.
>
> I was looking at this other thread:http://groups.google.com/group/restkit/browse_thread/thread/b30075024...

Dave Thompson

unread,
Feb 13, 2012, 7:46:20 PM2/13/12
to RestKit
Bob,

I picked up your mail. I'm fairly new to RestKit myself and probably
not the best person to answer all of your queries, but I'll take a
stab.

Let me paraphrase your thoughts into four questions:

1) Is it possible to load two linked entities from two distinct JSON
payloads received at different times, such that a Core Data
relationship is hydrated between them at the time the second entity is
loaded?

Yes.

2) How can this be done for 1-to-many relationships?

Where your Daughter entity is received after your Mother entity has
already been received and loaded, this is straightforward and
described in my response to
http://groups.google.com/group/restkit/browse_thread/thread/c89d0bbb9d5aef5a/cdf9ca81546e6f93#cdf9ca81546e6f93.
As well as the steps I describe there, you'll need to make sure you
have the primary key set up on the Mother entity. In that example,
this would be done as: teamMapping.primaryKeyAttribute = @"teamId";.

3) How can this be done for many-to-1 relationships?

Where your Mother entity is received after your Daughter entity has
already been received and loaded, things are trickier. There is no
built in RestKit support for this, as outlined in the question
http://groups.google.com/group/restkit/browse_thread/thread/cb5800badb772fd8#
. (An array of IDs doesn't work, nor do I think that would be a very
good implementation.) I therefore see two options that you have:

(a) Fork RestKit, add this functionality to it, and use your forked
copy of RestKit in your app. I don't know RestKit's internals, but my
gut feel is that this shouldn't be too difficult, given that the
implementation for (2) above already exists. This will likely result
in the cleanest implementation for your app. If you go down this
route, I'm sure they would be other people who would appreciate you
submitting the update back to Blake for inclusion in RestKit proper.

(b) Write some custom code within the objectLoader:didLoadObjects:
method in your RKObjectLoader delegate that handles the loading of the
Mother objects. For every Mother object loaded, retrieve the set of
Daughter objects with daughter.motherID == mother.motherID and
daughter.mother == nil. For every Daughter object in that set, set
daughter.mother = mother. (Recall from the linked question above that
Daughter objects must have both the relationship daughter.mother and
also the redundant foreign key daughter.motherID defined, to enable
RestKit's mapping.) This is the most straightforward solution to (3),
but your code will inevitable be less clean cut than if you did (a)
above.

4) How does this fit into my syncing solution?

RestKit is not itself a syncing solution. As any specific syncing
solution is highly dependent on business rules, you'll most likely
need to build your own. There is a question on StackOverflow that I
think is very useful for this:
http://stackoverflow.com/questions/5035132/how-to-sync-iphone-core-data-with-web-server-and-then-push-to-other-devices
. I personally find chris's answer to that question more useful than
the accepted answer, and will likely build my own syncing solution in
a similar manner to that he describes.

RestKit will, however, be hugely useful in managing the server
communication and object mapping within whatever syncing solution you
end up with.

I hope that helps,
Dave

Bob Spryn

unread,
Feb 14, 2012, 1:31:53 AM2/14/12
to RestKit
Dave. Awesome. You rock. I'll begin to try to piece this together.

Best,
Bob

On Feb 13, 5:46 pm, Dave Thompson <th03p...@gmail.com> wrote:
> Bob,
>
> I picked up your mail. I'm fairly new to RestKit myself and probably
> not the best person to answer all of your queries, but I'll take a
> stab.
>
> Let me paraphrase your thoughts into four questions:
>
> 1) Is it possible to load two linked entities from two distinct JSON
> payloads received at different times, such that a Core Data
> relationship is hydrated between them at the time the second entity is
> loaded?
>
> Yes.
>
> 2) How can this be done for 1-to-many relationships?
>
> Where your Daughter entity is received after your Mother entity has
> already been received and loaded, this is straightforward and
> described in my response tohttp://groups.google.com/group/restkit/browse_thread/thread/c89d0bbb9....
> As well as the steps I describe there, you'll need to make sure you
> have the primary key set up on the Mother entity. In that example,
> this would be done as: teamMapping.primaryKeyAttribute = @"teamId";.
>
> 3) How can this be done for many-to-1 relationships?
>
> Where your Mother entity is received after your Daughter entity has
> already been received and loaded, things are trickier. There is no
> built in RestKit support for this, as outlined in the questionhttp://groups.google.com/group/restkit/browse_thread/thread/cb5800bad...
> . (An array of IDs doesn't work, nor do I think that would be a very
> good implementation.) I therefore see two options that you have:
>
> (a) Fork RestKit, add this functionality to it, and use your forked
> copy of RestKit in your app. I don't know RestKit's internals, but my
> gut feel is that this shouldn't be too difficult, given that the
> implementation for (2) above already exists. This will likely result
> in the cleanest implementation for your app. If you go down this
> route, I'm sure they would be other people who would appreciate you
> submitting the update back to Blake for inclusion in RestKit proper.
>
> (b) Write some custom code within the objectLoader:didLoadObjects:
> method in your RKObjectLoader delegate that handles the loading of the
> Mother objects. For every Mother object loaded, retrieve the set of
> Daughter objects with daughter.motherID == mother.motherID and
> daughter.mother == nil. For every Daughter object in that set, set
> daughter.mother = mother. (Recall from the linked question above that
> Daughter objects must have both the relationship daughter.mother and
> also the redundant foreign key daughter.motherID defined, to enable
> RestKit's mapping.) This is the most straightforward solution to (3),
> but your code will inevitable be less clean cut than if you did (a)
> above.
>
> 4) How does this fit into my syncing solution?
>
> RestKit is not itself a syncing solution. As any specific syncing
> solution is highly dependent on business rules, you'll most likely
> need to build your own. There is a question on StackOverflow that I
> think is very useful for this:http://stackoverflow.com/questions/5035132/how-to-sync-iphone-core-da...

Bob Spryn

unread,
Feb 14, 2012, 1:37:00 AM2/14/12
to RestKit
One further thing, my question about syncing is less along the lines
of the post you pointed to (we actually have an almost identical
setup) but more along the lines of the one to many relationship, or
even more difficult a relationship going in both directions. Looks
like the answer is pretty much the same. Restkit doesn't have that
magic yet, and it would be custom code to handle it.

On Feb 13, 5:46 pm, Dave Thompson <th03p...@gmail.com> wrote:
> Bob,
>
> I picked up your mail. I'm fairly new to RestKit myself and probably
> not the best person to answer all of your queries, but I'll take a
> stab.
>
> Let me paraphrase your thoughts into four questions:
>
> 1) Is it possible to load two linked entities from two distinct JSON
> payloads received at different times, such that a Core Data
> relationship is hydrated between them at the time the second entity is
> loaded?
>
> Yes.
>
> 2) How can this be done for 1-to-many relationships?
>
> Where your Daughter entity is received after your Mother entity has
> already been received and loaded, this is straightforward and
> described in my response tohttp://groups.google.com/group/restkit/browse_thread/thread/c89d0bbb9....
> As well as the steps I describe there, you'll need to make sure you
> have the primary key set up on the Mother entity. In that example,
> this would be done as: teamMapping.primaryKeyAttribute = @"teamId";.
>
> 3) How can this be done for many-to-1 relationships?
>
> Where your Mother entity is received after your Daughter entity has
> already been received and loaded, things are trickier. There is no
> built in RestKit support for this, as outlined in the questionhttp://groups.google.com/group/restkit/browse_thread/thread/cb5800bad...
> . (An array of IDs doesn't work, nor do I think that would be a very
> good implementation.) I therefore see two options that you have:
>
> (a) Fork RestKit, add this functionality to it, and use your forked
> copy of RestKit in your app. I don't know RestKit's internals, but my
> gut feel is that this shouldn't be too difficult, given that the
> implementation for (2) above already exists. This will likely result
> in the cleanest implementation for your app. If you go down this
> route, I'm sure they would be other people who would appreciate you
> submitting the update back to Blake for inclusion in RestKit proper.
>
> (b) Write some custom code within the objectLoader:didLoadObjects:
> method in your RKObjectLoader delegate that handles the loading of the
> Mother objects. For every Mother object loaded, retrieve the set of
> Daughter objects with daughter.motherID == mother.motherID and
> daughter.mother == nil. For every Daughter object in that set, set
> daughter.mother = mother. (Recall from the linked question above that
> Daughter objects must have both the relationship daughter.mother and
> also the redundant foreign key daughter.motherID defined, to enable
> RestKit's mapping.) This is the most straightforward solution to (3),
> but your code will inevitable be less clean cut than if you did (a)
> above.
>
> 4) How does this fit into my syncing solution?
>
> RestKit is not itself a syncing solution. As any specific syncing
> solution is highly dependent on business rules, you'll most likely
> need to build your own. There is a question on StackOverflow that I
> think is very useful for this:http://stackoverflow.com/questions/5035132/how-to-sync-iphone-core-da...

Blake Watters

unread,
Feb 15, 2012, 11:28:09 AM2/15/12
to res...@googlegroups.com
Hi Bob et al -

There has been support for hydrating relationships on managed objects using primary key attributes for quite some time. This support requires you to do a couple of things:

1) Define an attribute mapping from your JSON payload to an attribute to keep track of the ID. (i.e. map user_id to userID on your mappable target entity)
2) Configure the RKManagedObjectMapping for your mappable target entity to include a relationship mapping for the relationship. So in the case of our user example, [objectMapping mapRelationship:@"user" withMapping:userMapping];
3) Configure your userMapping to indicate which attribute serves as the primary key for your object mapping. userMapping.primaryKeyAttribute = @"userID";
4) Configure the parent mapping to connect the relationship for you. [objectMapping connectRelationship:@"user" withObjectForPrimaryKeyAttribute:@"userID"];

RestKit will then connect the user relationship with the User entity where the primary key ID is equal to the mapped primary key attribute. No nested object are necessary.

Until this morning, this support worked exclusively for 1-to-1 relationships. I have just merged support that enables the support to work for one-to-many relationships such that you can send down an array of ID's and RestKit will fetch a set of objects and connect the one-to-many. It works identically as the above, with the exception that you need to configure your userID's (or whatever the attribute name is that will hold your object ID array) as a transformable so that RestKit can store the array on your mappable entity.

You can review the changes and supporting unit tests here: https://github.com/RestKit/RestKit/commit/789b0b99eb95c1c8f9f8bbf26638bf3a64d7a852

As to the larger concerns around syncing strategies, it is highly application dependent. I would love to get some generalized support in place at some point and there is a somewhat stale conversation around this pull request on Github: https://github.com/RestKit/RestKit/pull/197

I would love to continue that conversation on Github as the high email volume on this list makes it really hard for me to keep up and get anything meaningful done on the project simultaneously. 

Cheers,
Blake

--
Blake Watters
VP Engineering, GateGuru
Mobile: 919.260.3783
Get GateGuru for iOS: bit.ly/ggitunes
Get GateGuru for Android: bit.ly/ggandroid

Interested in creating the mobile travel experience of the future? We're hiring!

Bob Spryn

unread,
Feb 15, 2012, 1:13:57 PM2/15/12
to RestKit
Awesome Blake. This will get me the rest of the way there.

Best,
Bob

On Feb 15, 9:28 am, Blake Watters <bl...@gateguruapp.com> wrote:
> Hi Bob et al -
>
> There has been support for hydrating relationships on managed objects using primary key attributes for quite some time. This support requires you to do a couple of things:
>
> 1) Define an attribute mapping from your JSON payload to an attribute to keep track of the ID. (i.e. map user_id to userID on your mappable target entity)
> 2) Configure the RKManagedObjectMapping for your mappable target entity to include a relationship mapping for the relationship. So in the case of our user example, [objectMapping mapRelationship:@"user" withMapping:userMapping];
> 3) Configure your userMapping to indicate which attribute serves as the primary key for your object mapping. userMapping.primaryKeyAttribute = @"userID";
> 4) Configure the parent mapping to connect the relationship for you. [objectMapping connectRelationship:@"user" withObjectForPrimaryKeyAttribute:@"userID"];
>
> RestKit will then connect the user relationship with the User entity where the primary key ID is equal to the mapped primary key attribute. No nested object are necessary.
>
> Until this morning, this support worked exclusively for 1-to-1 relationships. I have just merged support that enables the support to work for one-to-many relationships such that you can send down an array of ID's and RestKit will fetch a set of objects and connect the one-to-many. It works identically as the above, with the exception that you need to configure your userID's (or whatever the attribute name is that will hold your object ID array) as a transformable so that RestKit can store the array on your mappable entity.
>
> You can review the changes and supporting unit tests here:https://github.com/RestKit/RestKit/commit/789b0b99eb95c1c8f9f8bbf2663...
>
> As to the larger concerns around syncing strategies, it is highly application dependent. I would love to get some generalized support in place at some point and there is a somewhat stale conversation around this pull request on Github:https://github.com/RestKit/RestKit/pull/197
>
> I would love to continue that conversation on Github as the high email volume on this list makes it really hard for me to keep up and get anything meaningful done on the project simultaneously.
>
> Cheers,
> Blake
>
> --
> Blake Watters
> VP Engineering, GateGuru
> bl...@gateguruapp.com (mailto:bl...@gateguruapp.com)
> Mobile: 919.260.3783
> www. (http://www.gateguruapp.com)gateguruapp.com(http://gateguruapp.com)
> Get GateGuru for iOS: bit.ly/ggitunes (http://bit.ly/ggitunes)
> Get GateGuru for Android: bit.ly/ggandroid (http://bit.ly/ggandroid)
>
> Interested in creating the mobile travel experience of the future? We're hiring! (http://gateguruapp.com/careers/)
>
>
>
>
>
>
>
> On Tuesday, February 14, 2012 at 1:37 AM, Bob Spryn wrote:
> > One further thing, my question about syncing is less along the lines
> > of the post you pointed to (we actually have an almost identical
> > setup) but more along the lines of the one to many relationship, or
> > even more difficult a relationship going in both directions. Looks
> > like the answer is pretty much the same. Restkit doesn't have that
> > magic yet, and it would be custom code to handle it.
>
> > > On Feb 13, 5:16 am, Bob Spryn <bobsp...@gmail.com (http://gmail.com)> wrote:
>
> > > > Bumping this as I'm sort of spinning my wheels until I figure this
> > > > out.
>

Vinzenz-E. Weber

unread,
Mar 9, 2012, 9:49:58 AM3/9/12
to RestKit
Hi,

I am working on that same problem for some days by now.
But my app keeps crashing when I try to map a one-to-many relationship
by primary key.
Hoping for some help, I posted the relevant snippet code in
https://gist.github.com/2006812

Thanks!
Vinzenz


On 15 Feb., 19:13, Bob Spryn <bobsp...@gmail.com> wrote:
> Awesome Blake. This will get me the rest of the way there.
>
> Best,
> Bob
>
> On Feb 15, 9:28 am, Blake Watters <bl...@gateguruapp.com> wrote:
>
>
>
>
>
>
>
> > Hi Bob et al -
>
> > There has been support for hydrating relationships on managed objects using primary key attributes for quite some time. This support requires you to do a couple of things:
>
> > 1) Define an attribute mapping from your JSON payload to an attribute to keep track of the ID. (i.e. map user_id to userID on your mappable target entity)
> > 2) Configure the RKManagedObjectMapping for your mappable target entity to include arelationshipmapping for therelationship. So in the case of our user example, [objectMapping mapRelationship:@"user" withMapping:userMapping];
> > 3) Configure your userMapping to indicate which attribute serves as the primary key for your object mapping. userMapping.primaryKeyAttribute = @"userID";
> > 4) Configure the parent mapping to connect therelationshipfor you. [objectMapping connectRelationship:@"user" withObjectForPrimaryKeyAttribute:@"userID"];
>
> > RestKit will then connect the userrelationshipwith the User entity where the primary key ID is equal to the mapped primary key attribute. No nested object are necessary.
>
> > Until this morning, this support worked exclusively for 1-to-1 relationships. I have just merged support that enables the support to work for one-to-many relationships such that you can send down an array of ID's and RestKit will fetch a set of objects and connect the one-to-many. It works identically as the above, with the exception that you need to configure your userID's (or whatever the attribute name is that will hold your object ID array) as a transformable so that RestKit can store the array on your mappable entity.
>
> > You can review the changes and supporting unit tests here:https://github.com/RestKit/RestKit/commit/789b0b99eb95c1c8f9f8bbf2663...
>
> > As to the larger concerns around syncing strategies, it is highly application dependent. I would love to get some generalized support in place at some point and there is a somewhat stale conversation around this pull request on Github:https://github.com/RestKit/RestKit/pull/197
>
> > I would love to continue that conversation on Github as the high email volume on this list makes it really hard for me to keep up and get anything meaningful done on the project simultaneously.
>
> > Cheers,
> > Blake
>
> > --
> > Blake Watters
> > VP Engineering, GateGuru
> > bl...@gateguruapp.com (mailto:bl...@gateguruapp.com)
> > Mobile: 919.260.3783
> > www. (http://www.gateguruapp.com)gateguruapp.com(http://gateguruapp.com)
> > Get GateGuru for iOS: bit.ly/ggitunes (http://bit.ly/ggitunes)
> > Get GateGuru for Android: bit.ly/ggandroid (http://bit.ly/ggandroid)
>
> > Interested in creating the mobile travel experience of the future? We're hiring! (http://gateguruapp.com/careers/)
>
> > On Tuesday, February 14, 2012 at 1:37 AM, Bob Spryn wrote:
> > > One further thing, my question about syncing is less along the lines
> > > of the post you pointed to (we actually have an almost identical
> > > setup) but more along the lines of the one to manyrelationship, or
> > > even more difficult arelationshipgoing in both directions. Looks
> > > like the answer is pretty much the same. Restkit doesn't have that
> > > magic yet, and it would be custom code to handle it.
>
> > > On Feb 13, 5:46 pm, Dave Thompson <th03p...@gmail.com (http://gmail.com)> wrote:
> > > > Bob,
>
> > > > I picked up your mail. I'm fairly new to RestKit myself and probably
> > > > not the best person to answer all of your queries, but I'll take a
> > > > stab.
>
> > > > Let me paraphrase your thoughts into four questions:
>
> > > > 1) Is it possible to load two linked entities from two distinct JSON
> > > > payloads received at different times, such that a Core Data
> > > >relationshipis hydrated between them at the time the second entity is
> > > > Daughter objects must have both therelationshipdaughter.mother and
> > > > also the redundant foreign key daughter.motherID defined, to enable
> > > > RestKit's mapping.) This is the most straightforward solution to (3),
> > > > but your code will inevitable be less clean cut than if you did (a)
> > > > above.
>
> > > > 4) How does this fit into my syncing solution?
>
> > > > RestKit is not itself a syncing solution. As any specific syncing
> > > > solution is highly dependent on business rules, you'll most likely
> > > > need to build your own. There is a question on StackOverflow that I
> > > > think is very useful for this:http://stackoverflow.com/questions/5035132/how-to-sync-iphone-core-da...
> > > > . I personally find chris's answer to that question more useful than
> > > > the accepted answer, and will likely build my own syncing solution in
> > > > a similar manner to that he describes.
>
> > > > RestKit will, however, be hugely useful in managing the server
> > > > communication and object mapping within whatever syncing solution you
> > > > end up with.
>
> > > > I hope that helps,
> > > > Dave
>
> > > > On Feb 13, 5:16 am, Bob Spryn <bobsp...@gmail.com (http://gmail.com)> wrote:
>
> > > > > Bumping this as I'm sort of spinning my wheels until I figure this
> > > > > out.
>
> > > > > On Feb 8, 4:01 pm, Bob Spryn <bobsp...@gmail.com (http://gmail.com)> wrote:
>
> > > > > > So I'm trying to put together the proper procedure for doing
> > > > > >relationshipmapping with keys instead of embedding the objects in the
> > > > > > json, as the embedding piece is really hammering our API and timeouts
> > > > > > are occurring.
>
> > > > > > I was looking at this other thread:http://groups.google.com/group/restkit/browse_thread/thread/b30075024...
>
> > > > > > Is there some documentation or an example somewhere of the exact
> > > > > > correct way to do this?
>
> > > > > > My followup question is this: Once my mapping with id's is working,
> > > > > > how should I perform an initial sync to pull down all the data? How
> > > > > > does this work when objects may be pointing via idrelationshipto
> > > > > > other objects that don't yet exist in core data? Is it going to make
> > > > > > an individual http request in the middle of a large request for a
> > > > > > singular object because of therelationship, or will it somehow batch

Vinzenz-E. Weber

unread,
Mar 9, 2012, 9:59:03 AM3/9/12
to RestKit
To clarify:

The JSON file has got exercises and workouts and I am trying to map
the keypath workouts.exercises.exercise to one of the objects by
primary key given by the keypath exercises.uid! So
WorkoutExercise.exercise should have the proper Exercise set.


On 9 Mrz., 15:49, "Vinzenz-E. Weber" <vinz...@blockhausmedien.at>
wrote:
> Hi,
>
> I am working on that same problem for some days by now.
> But my app keeps crashing when I try to map a one-to-manyrelationship
> by primary key.
> Hoping for some help, I posted the relevant snippet code inhttps://gist.github.com/2006812
Reply all
Reply to author
Forward
0 new messages