Skip to content

Inverse Relationships

Jens Alfke edited this page Jun 13, 2015 · 1 revision

In Couchbase Lite 1.1, CBLModel now supports computed inverse-relation properties. This is a typical ORM feature, also found in Core Data.

For example, if the Album class has a relation @property Artist* artist (i.e. the JSON property value is the docID of a document corresponding to an Artist model), then you can create a property on Artist like @property (readonly) NSArray* albums, whose value is an array of the Album objects whose artist property points to the receiver.

Behind the scenes, there's no JSON property backing this. Its value is computed on demand by creating and querying a view that indexes the artist property of every album document.

How To Do It

  1. At launch time, register the document type property of both model classes with the database's ModelFactory.
  2. Define the @property in the class interface. It must be a read-only NSArray*.
  3. In the class implementation, declare the property as @dynamic.
  4. Implement a class method +propertyItemClass that returns the class that has the inverse relation, i.e. the class of the items in the array to be returned.
  5. Implement a class method +propertyInverseRelation that returns a string naming the relation property in the other class that should be queried.

Example

As in the introduction above, assume there is an Album class that has a regular relation @property Artist* artist (i.e. the JSON property value is the docID of a document corresponding to an Artist model.) We then create the inverse relation as follows:

@interface Artist
    @property (readonly) NSArray* albums;
    ...

@implementation Artist
    ...
    @dynamic albums;
    + (Class) albumsItemClass { return [Album class]; }
    + (NSString*) albumsInverseRelation { return @"artist"; }
    ...

At runtime we register the document types:

    [database.modelFactory registerClass: [Album class] forDocumentType: @"album"];
    [database.modelFactory registerClass: [Artist class] forDocumentType: @"artist"];

Limitations

  • The property value is recomputed on every call. Database queries are not cheap, so accessing the property too often could easily become a performance bottleneck. You may want to cache the value. In the future we could add caching to the framework (invalidating the cache when the view index changes.)
  • These properties are not KV-observable (that would be great to add later, but it would require something like a LiveQuery, and would have to be carefully optimized to be scaleable.)