Realm-js: How do I do a one-to-one relation ?

Created on 2 Feb 2016  路  5Comments  路  Source: realm/realm-js

Or one-to-many - from the one side (for example a user has many PhoneNumber's. How do I define the Owner of a PhoneNumber object in the PhoneNumber schema ?)

T-Help

Most helpful comment

var PhoneNumberSchema = {
    name: 'PhoneNumber',
    properties: {
        number: 'string',
    }
};

var OwnerSchema = {
    name: 'Owner',
    properties: {
        homeNumber: 'PhoneNumber',
        workNumber: {type: 'object', objectType: 'PhoneNumber'},
        mobileNumbers: {type: 'list', objectType: 'PhoneNumber'}
    }
};

var realm = new Realm({schema: [PhoneNumberSchema, OwnerSchema]});

Here is the section from the docs on model definitions. I am still working on this and it isn't yet ready to be put up but maybe it will help:

Models and Objects

Realm data models are defined by passed schema information into a Realm object during initializion. The schema for an object consists of the object's name and a set of properties each of which has a name, type and optional default and optional designations. You can pass the name from other object schema for the type to create links between objects, and Realm also supports lists of links to other objects.

var Realm = require('realm');

let DogSchema = {
  name: 'Dog',
  properties: {
    name: 'string',
    age:  'int'
  }
}
let PersonSchema = {
  name: 'Person',
  properties: {
    name:     {type: 'string'},
    picture:  {type: 'data', optional: true}, // optional property
    birthday: {type: 'date'},
    dogs:     {type: 'list', objectType: 'Dog'}
  }
}

// Initialize a Realm with Dog and Person models
let realm = new Realm({schema: [DogSchema, PersonSchema]});

If you'd prefer your objects inherit from a prototype, you just need to define the schema on the prototype object and instead pass in the constructor when creating a realm:

function Person() {}
Person.prototype = {
    schema: PersonSchema,
    get age() {
        return Math.floor((Date.now() - this.birthday.getTime()) / 31557600000);
    },
};

let realm = new Realm({schema: [Person]});

Once you have defined your object models you can create and fetch objects from the realm

var rex = realm.create('Dog', { name: 'Rex', age: 2});

// you can access and set all properties defined in your model
console.log('Dog name is ' + rex.name);
rex.age = 3;

Basic Property Types

Realm supports the following basic types: bool, int, float, double, string, data, and date.

  • bool properties are mapped to JavaScript Boolean objects
  • int, float, and double properties map to JavaScript Number objects. Internally 'int' and 'double' are stored as 64 bits while float is stored with 32 bits.
  • string properties map to String
  • data properties map to ArrayBuffeer
  • date properties map to Date

Object Properties

For object types you must specify the underlying objectType for each property. For single object properties you can specify the objectType as the primary type as shorthand:

const OwnerSchema = {
  name: 'Owener',
  properties: {
    // All of the following property definitions are equivalent
    dog:    'Dog',
    doggie: { type: 'Dog'},
    doge:   { type: 'object', objectType: 'Dog'}
  }
}

When acessing object properties, you can access nested properties using normal property syntax:

var nameString = owner.dog.name;
owner.dog.age = 3;
owner.doggie = { 'Dexter', 5 }; // create a new Dog by setting the property to valid JSON 
owner.doge = owner.dog;         // set both properties to the same dog instance

List Properties

For list properties you must specify the property type as list as well as the objectType:

const OwnerSchema = {
  name: 'Owner',
  properties: {
    dogs: { type: 'list', objectType: 'Dog'}
  }
}

When accessing list properties a RealmArray object is returned. RealmArray has methods very similiar to a vanilla JavaScript array. The big difference is that any changes made to a RealmArray are automatically persisted to the underlying Realm. Additionaly RealmArrays belong to the underlying object they were aquired from - you can only get RealmArray instances by calling a property getting and cannot create them manually.

var listOfDogs = ownerObject.dogs;
var thirdDogName = listOfDogs[2].name;      // access using an array index

// add a new dog to a list
realm.write(function() {
  listOfDogs.push({'Ronnie, 6'});  
});

Optional Properties

Properties can be declared as optional or non-optional by specifying the optional designator in your property definition:

const PersonSchema = {
  name: 'Person',
  properties: {
    name:     {type: 'string'},                   // required property
    birtyday: {type: 'date', optional: true},     // optional property
    dog:      {type: 'object', objectType: 'Dog'} // object properties are always optional
  }
}

let realm = new Realm({schema: [PersonSchema, DogSchema]});
realm.write(function() {
  // optional properties can be ommitted when creating objects
  // here we do not specify the optional `dog` property
  var charlie = realm.create('Person', { 
    name: 'Charlie', 
    birthdate: new Date(date) 
  }); 

  // optional properties can be set to `underfined` or `null`
  charlie.birthdate = undefined;  
});

Default Property Values

Default property values can be specified by setting the default designator in the property definition. To use a default value leave the property unspecified during object creation.

const DogSchema = {
  name: 'Dog',
  properties: {
    name:     {type: 'string'},              // no default
    neutered: {type: 'bool', default: false} // default value
  }
}

realm.write(function() {
  realm.create('Dog', { name: 'Rosie' });
})

Primary Keys

You can specify the primaryKey property in an object model for string and int properties. Declaring a primary key allows objects to be looked up and updated efficiently and enforces uniqueness for each value. Once an object with a primary key is added to a Realm, the primary key cannot be changed.

const PersonSchema = {
  name: 'Person',
  primaryKey: 'id',
  properties: {
    id:   'int',    // primary key
    name: 'string'
  }
};

All 5 comments

var PhoneNumberSchema = {
    name: 'PhoneNumber',
    properties: {
        number: 'string',
    }
};

var OwnerSchema = {
    name: 'Owner',
    properties: {
        homeNumber: 'PhoneNumber',
        workNumber: {type: 'object', objectType: 'PhoneNumber'},
        mobileNumbers: {type: 'list', objectType: 'PhoneNumber'}
    }
};

var realm = new Realm({schema: [PhoneNumberSchema, OwnerSchema]});

Here is the section from the docs on model definitions. I am still working on this and it isn't yet ready to be put up but maybe it will help:

Models and Objects

Realm data models are defined by passed schema information into a Realm object during initializion. The schema for an object consists of the object's name and a set of properties each of which has a name, type and optional default and optional designations. You can pass the name from other object schema for the type to create links between objects, and Realm also supports lists of links to other objects.

var Realm = require('realm');

let DogSchema = {
  name: 'Dog',
  properties: {
    name: 'string',
    age:  'int'
  }
}
let PersonSchema = {
  name: 'Person',
  properties: {
    name:     {type: 'string'},
    picture:  {type: 'data', optional: true}, // optional property
    birthday: {type: 'date'},
    dogs:     {type: 'list', objectType: 'Dog'}
  }
}

// Initialize a Realm with Dog and Person models
let realm = new Realm({schema: [DogSchema, PersonSchema]});

If you'd prefer your objects inherit from a prototype, you just need to define the schema on the prototype object and instead pass in the constructor when creating a realm:

function Person() {}
Person.prototype = {
    schema: PersonSchema,
    get age() {
        return Math.floor((Date.now() - this.birthday.getTime()) / 31557600000);
    },
};

let realm = new Realm({schema: [Person]});

Once you have defined your object models you can create and fetch objects from the realm

var rex = realm.create('Dog', { name: 'Rex', age: 2});

// you can access and set all properties defined in your model
console.log('Dog name is ' + rex.name);
rex.age = 3;

Basic Property Types

Realm supports the following basic types: bool, int, float, double, string, data, and date.

  • bool properties are mapped to JavaScript Boolean objects
  • int, float, and double properties map to JavaScript Number objects. Internally 'int' and 'double' are stored as 64 bits while float is stored with 32 bits.
  • string properties map to String
  • data properties map to ArrayBuffeer
  • date properties map to Date

Object Properties

For object types you must specify the underlying objectType for each property. For single object properties you can specify the objectType as the primary type as shorthand:

const OwnerSchema = {
  name: 'Owener',
  properties: {
    // All of the following property definitions are equivalent
    dog:    'Dog',
    doggie: { type: 'Dog'},
    doge:   { type: 'object', objectType: 'Dog'}
  }
}

When acessing object properties, you can access nested properties using normal property syntax:

var nameString = owner.dog.name;
owner.dog.age = 3;
owner.doggie = { 'Dexter', 5 }; // create a new Dog by setting the property to valid JSON 
owner.doge = owner.dog;         // set both properties to the same dog instance

List Properties

For list properties you must specify the property type as list as well as the objectType:

const OwnerSchema = {
  name: 'Owner',
  properties: {
    dogs: { type: 'list', objectType: 'Dog'}
  }
}

When accessing list properties a RealmArray object is returned. RealmArray has methods very similiar to a vanilla JavaScript array. The big difference is that any changes made to a RealmArray are automatically persisted to the underlying Realm. Additionaly RealmArrays belong to the underlying object they were aquired from - you can only get RealmArray instances by calling a property getting and cannot create them manually.

var listOfDogs = ownerObject.dogs;
var thirdDogName = listOfDogs[2].name;      // access using an array index

// add a new dog to a list
realm.write(function() {
  listOfDogs.push({'Ronnie, 6'});  
});

Optional Properties

Properties can be declared as optional or non-optional by specifying the optional designator in your property definition:

const PersonSchema = {
  name: 'Person',
  properties: {
    name:     {type: 'string'},                   // required property
    birtyday: {type: 'date', optional: true},     // optional property
    dog:      {type: 'object', objectType: 'Dog'} // object properties are always optional
  }
}

let realm = new Realm({schema: [PersonSchema, DogSchema]});
realm.write(function() {
  // optional properties can be ommitted when creating objects
  // here we do not specify the optional `dog` property
  var charlie = realm.create('Person', { 
    name: 'Charlie', 
    birthdate: new Date(date) 
  }); 

  // optional properties can be set to `underfined` or `null`
  charlie.birthdate = undefined;  
});

Default Property Values

Default property values can be specified by setting the default designator in the property definition. To use a default value leave the property unspecified during object creation.

const DogSchema = {
  name: 'Dog',
  properties: {
    name:     {type: 'string'},              // no default
    neutered: {type: 'bool', default: false} // default value
  }
}

realm.write(function() {
  realm.create('Dog', { name: 'Rosie' });
})

Primary Keys

You can specify the primaryKey property in an object model for string and int properties. Declaring a primary key allows objects to be looked up and updated efficiently and enforces uniqueness for each value. Once an object with a primary key is added to a Realm, the primary key cannot be changed.

const PersonSchema = {
  name: 'Person',
  primaryKey: 'id',
  properties: {
    id:   'int',    // primary key
    name: 'string'
  }
};

OK thanks for that.

Another question regarding this - is the relation saved only as a reference or as a copy of the object ?

@dorongutman the relations are saved as references in the database, but you will get a new JS object on every access that references the same underlying object in the database.

@dorongutman : Is this good to close now?

yes

Was this page helpful?
0 / 5 - 0 ratings

Related issues

CrystalRanita picture CrystalRanita  路  3Comments

texas697 picture texas697  路  3Comments

emrehayirci picture emrehayirci  路  3Comments

max-zu picture max-zu  路  3Comments

bdebout picture bdebout  路  3Comments