In some web applications, we need to define a one-to-many relationship between two entities. For example, let's take github.
Example: One-to-Many relationship exists between user
and repository
. User pksunkara
have 2 repositories octonode
and hub
The entities are defined as the following:
var resourceful = require('resourceful');
module.exports = resourceful.define('user', function () {
this.string('name');
});
var resourceful = require('resourceful');
module.exports = resourceful.define('repository', function () {
this.string('name');
this.parent('User');
});
The documents are saved in couchdb as following:
[
{
_id: 'user/pksunkara',
name: 'pksunkara',
resource: 'User',
repository_ids: ['octonode', 'hub']
},
{
_id: 'repository/user/pksunkara/octonode',
name: 'octonode',
resource: 'Repository',
user_id: 'pksunkara'
},
{
_id: 'repository/user/pksunkara/hub',
name: 'hub',
resource: 'Repository',
user_id: 'pksunkara'
}
]
The following queries are supported:
var User = require('./user')
, Repository = require('./repository');
// Get children using parent id
User.repositories('pksunkara', callback);
Repository.byUser('pksunkara', callback);
// Get children using parent obj
User.get('pksunkara', function (err, user) {
user.repositories(callback);
});
// Create a child using parent id
User.createRepository('pksunkara', { id: 'police', name: 'police' }, callback);
// Create a child using parent obj
User.get('pksunkara', function (err, user) {
user.createRepository({ id: 'police', name: 'police' }, callback);
});
// Get parent using child obj
Repository.get('user/pksunkara/hub', function (err, repository) {
repository.user(callback);
});
In some web applications, we need to define a many-to-many relationship between two entities. For examples, let's take github.
Example: Many-to-Many relationship exists between user
and organization
. Organization nodejitsu
have 2 users pksunkara
and marak
whereas organization nodeapps
have only one user marak
.
Note: Organization and User are first layer resources, meaning they should never have a parent defined in their resource definition
In standard SQL databases, this relationship is represented using an intermediate member
entity with two foreign keys user_id
and organization_id
.
This many-to-many in resourceful works by defining 2 intermediate entities named member
and membership
and creating 2 one-to-many relationships instead of 1 many-to-many relationship. user
is one-to-many with membership
and organization
is one-to-many with member
.
The entities are defined as the following:
var resourceful = require('resourceful');
module.exports = resourceful.define('user', function () {
this.string('name'):
});
var resourceful = require('resourceful');
module.exports = resourceful.define('organization', function () {
this.string('name');
});
var resourceful = require('resourceful');
module.exports = resourceful.define('member', function () {
this.parent('Organization');
});
var resourceful = require('resourceful');
module.exports = resourceful.define('membership', function () {
this.parent('User');
});
The documents are saved in couchdb as following:
[
{
_id: 'user/pksunkara',
name: 'pksunkara',
resource: 'User',
membership_ids: ['nodejitsu']
},
{
_id: 'user/marak',
name: 'marak',
resource: 'User',
membership_ids: ['nodejitsu', 'nodeapps']
},
{
_id: 'organization/nodejitsu',
name: 'nodejitsu',
resource: 'Organization',
member_ids: ['marak', 'pksunkara']
},
{
_id: 'organization/nodeapps',
name: 'nodeapps',
resource: 'Organization',
member_ids: ['marak']
},
{
_id: 'membership/user/marak/nodejitsu',
resource: 'Membership',
user_id: 'marak'
},
{
_id: 'membership/user/pksunkara/nodejitsu',
resource: 'Membership',
user_id: 'pksunkara'
},
{
_id: 'membership/user/marak/nodeapps',
resource: 'Membership',
user_id: 'marak'
},
{
_id: 'member/organization/nodejitsu/marak',
resource: 'Member',
organization_id: 'nodejitsu'
},
{
_id: 'member/organization/nodejitsu/pksunkara',
resource: 'Member',
organization_id: 'nodejitsu'
},
{
_id: 'member/organization/nodeapps/marak',
resource: 'Member',
organization_id: 'nodeapps'
}
]
The following queries are supported:
var User = require('./user')
, Organization = require('./organization')
, Membership = require('./membership')
, Member = require('./member');
// Get users' names in an organization given by id
Organization.get('nodejitsu', function (err, org) {
console.log(org.membership_ids);
// => ['marak', 'pksunkara']
});
// Get organizations' names for an user given by id
User.get('marak', function (err, user) {
console.log(org.member_ids);
// => ['nodejitsu', 'nodeapps']
});
// An User joins an Organization
User.createMembership('pksunkara', { id: 'nodeapps' }, function () {
Organization.createMember('nodeapps', { id: 'pksunkara' }, callback);
});
// An User leaves an Organization
Membership.destroy('user/pksunkara/nodeapps', function () {
Member.destroy('organization/nodeapps/pksunkara', callback);
});