Chapter 10. Implementing Unidirectional Non-Functional Associations with AngularJS and Parse.com

Table of Contents

1. One-to-Many or Many-to-Many Relations in Parse
1.1. Using Array
1.2. Using Join Table
1.3. Using Parse Relation
2. New issues
3. Encode our Web Application with Unidirectional Non-Functional Association
3.1. Special processing for Date
3.2. List Objects Use Case
3.3. Create Object Use Case
3.4. Update Object Use Case
3.5. Delete Object Use Case
4. Run the App and Get the Code

A unidirectional non-functional association is either one-to-many or many-to-many. In both cases such an association is represented, or implemented, with the help of a multi-valued reference property.

In this chapter, we show

  1. how to handle the one-to-many or many-to-many relations between objects using Parse, as a backend storage service,

  2. how to process the relations using Angular $http and Parse REST API based on an association-free information design model with multi-valued reference properties representing unidirectional non-functional associations,

  3. how to write the view and controller code for our web application.

1. One-to-Many or Many-to-Many Relations in Parse

As we know that Parse provides four ways to solve the relations between objects: Pointer, Array, Join Table and Parse Relation. The last three are using for One-to-Many or Many-to-Many relation, which appears between Book and Author. A mulit-valued reference property, such as the property authors of the object type Book, allows storing a set of references to objects of some type, such as Author; the property authoredBooks of the object type Author, allows storing a set of references to objects of Book.

The starting point for building the relationship using Array between book and author objects is an association-free design model like following:

Figure 10.1. Book-Author association-free model

Book-Author association-free model


1.1. Using Array

1.1.1. Create/Update Array

Suppose we know one book which has two authors. If we want to build this relation, we should insert these two authors into the property authors of this book:

$http( {
  method: 'PUT',
  url: 'https://api.parse.com/1/classes/Book/' + book.objectId,
  data: { authors: [ author1, author2]}
});

These two author objects will be saved in this book record. But notice that if we update or delete an author record, such as author1, the old information about author1 in this book record will not be automatically updated or deleted, cause the Array is not really the relation in the database but the logical structure in our minds.

1.1.2. Retrieve Objects

If we have got a book and want to get its authors, there is nothing that need to do, cause this book record had these information already.

1.1.3. Remove Array

Suppose we want to delete all the authors of this book record:

$http( {
  method: 'PUT',
  url: 'https://api.parse.com/1/classes/book/' + book.objectId,
  data: { authors: { __op: 'Delete'}}
});

1.2. Using Join Table

Join Table is the idea from classical database. When there is a Many-to-Many relation, we build two One-to-Many relations, which means to combine every objectId from both sides together to build a new separate table in which the relationship is tracked:

Figure 10.2. Book-Author-JoinTable model

Book-Author-JoinTable model


(bookObjectId, authorObjectId) will be combined together as a primary key.

1.2.1. Create Join Table

Suppose we have one book (book1) and it has two authors (author1 and author2), another book (book2) has one author (author2):

// author1 and author2 have authored book1
twoAuthors.forEach( function ( a) {
  $http( {
    method: 'POST',
    url: 'https://api.parse.com/1/classes/joinBookAuthor',
    data: {
      bookObjectId: book1.objectId,
      authorObjectId: a.objectId
    }
  });
});

// author2 has authored book2
$http( {
  method: 'POST',
  url: 'https://api.parse.com/1/classes/joinBookAuthor',
  data: {
    bookObjectId: book2.objectId,
    authorObjectId: author2.objectId
  }
});

1.2.2. Update Join Table

Suppose we want to update that author1 had also authored book2, it's acturally a "Create" event, that create a new book-author record:

$http( {
  method: 'POST',
  url: 'https://api.parse.com/1/classes/joinBookAuthor',
  data: {
    bookObjectId: book2.objectId,
    authorObjectId: author1.objectId
  }
});

By updating that author1 haven't authored book2, it is acturally to delete the corresponding record:

$http( {
  method: 'DELETE',
  url: 'https://api.parse.com/1/classes/joinBookAuthor',
  params: { 
    where: {
      bookObjectId: book2.objectId,
      authorObjectId: author1.objectId
    }
  }
});

1.2.3. Remove Join Table

The Join Table in Parse will be saved as a class and Parse did not offer a function for droping a class. So we can not remove the whole Join Table but just make it empty like several "Update" events. First to GET all records in the joinBookAuthor, then to DELETE them all.

1.3. Using Parse Relation

Before using the method of Parse Relation we discuss a little about what the Parse Relation really is.

If we create some books and authors as the test data in Parse, the book records with Parse Relations will be:

After clicking the one of these View Relations buttons, we will see a kind of list named "authors" showing on the left side, which keeps all the related authors:

1.3.1. Create/Update Parse Relation

Suppose we got a book and want to relate to two authors:

$http( {
  method: 'PUT',
  url: 'https://api.parse.com/1/classes/Book/' + book.objectId,
  data: {
    authors: {
      __op: 'AddRelation',  // or 'RemoveRelation'
      objects: [{
        __type: 'Pointer',
        className: 'Author',
        objectId: author1.objectId
      },
      {
        __type: 'Pointer',
        className: 'Author',
        objectId: author2.objectId
      }]
    }
  }
})

When we want to delete one or more certain related authors from a book, it should be also a "Update" event but using __op: 'RemoveRelation'. Besides, after updated the basic information about an author record (name, birthDate or deathDate) or deleted an author record, we do not need to change the Parse Relations manually.

1.3.2. Retrieve Objects

Suppose we got a book want to find all information about its authors, we should use a Parse built-in operation $relatedTo:

$http({
  method: 'GET',
  url: 'https://api.parse.com/1/classes/Author',
  params: {
    where: {
      $relatedTo: {
        object: {
          __type: 'Pointer',
          className: 'Book',
          objectId: book.objectId
        },
        key: 'authors'
      }
    }
  }
})

1.3.3. Remove Parse Relation

Parse didn't allow user directly to remove the field in type of Relation, we can only use its RemoveRelation operation and a loop to delete all related records.