I have the following situation: There are a Divisions, each consist of List of elements. Those elements can be LineChart, DataTable and etc. I want to find a design solution, where Division can contain DivisionElements, which can be LineChart or DataTable ( there are more elements, but let's talk just about 2 ). While Object-Oriented Database commonly support Inheritance, I do have a feeling Realm does not really support it. It is more based on composition. Here is pseudo data-structure:
{
divisions: [
{
divisionTitle: 'Ergebnisplan',
divisionID: '1',
divisionComponents: [
{
componentType: 'dataTable',
componentID: '11',
columnTitles: ['', 'Year 2021', 'Year 2022', 'Year 2023', 'Year 2024'],
data: {
rowValues: [
{ 'Ordinary Income': ['141275507', '132018907', '142740563', '149158240'] },
{ 'Ordinary Expenses': ['134067604', '140766430', '158197815', '160843652'] },
],
},
},
],
},
{
divisionTitle: 'Entwicklung und Zusammensetzung der Erträge und Aufwendungen',
divisionID: '2',
divisionComponents: [
{
componentType: 'lineChart',
componentID: '21',
xTitle: 'year',
yTitle: 'earnings',
lines: [
{
lineLabel: 'income',
lineColor: 'green',
interpolation: 'linear',
data: [
{ year: '2021', earnings: '141275507' },
{ year: '2022', earnings: '132018907' },
{ year: '2023', earnings: '142740563' },
{ year: '2024', earnings: '149158240' },
],
},
{
lineLabel: 'expenses',
lineColor: 'red',
interpolation: 'linear',
data: [
{ year: '2021', earnings: '134067604' },
{ year: '2022', earnings: '140766430' },
{ year: '2023', earnings: '158197815' },
{ year: '2024', earnings: '160843652' },
],
},
],
},
],
},
],
}
In my React-Native code Division dynamically ( through switch statements ) creates it's children ( LineChart, DataTable and etc ).
- I tried to design the solution myself and this is what I came up with:
export default class DivisionModel extends Realm.Object {
static schema = {
name: 'DivisionModel',
primaryKey: 'divisionID',
properties: {
title: 'string',
divisionID: 'int',
components: { type: 'list', objectType: 'DivisionComponentModel' },
},
};
}
export default class DivisionComponentModel extends Realm.Object {
static schema = {
name: 'DivisionComponentModel',
primaryKey: 'divisionComponentID',
properties: {
divisionID: 'int',
divisionComponentID: 'int',
componentID: 'int',
componentType: 'string',
},
};
}
export default class DataTableModel extends Realm.Object {
static schema = {
name: 'DataTableModel',
primaryKey: 'componentID',
properties: {
componentID: 'int',
columnTitles: 'string[]',
rowTitles: 'string[]',
numberOfColumns: 'int',
numberOfRows: 'int',
rowsData: { type: 'list', objectType: 'DataTableRowModel' },
},
};
}
export default class LineChartModel extends Realm.Object {
static schema = {
name: 'LineChartModel',
primaryKey: 'componentID',
properties: {
componentID: 'int',
xTitle: 'string',
yTitle: 'string',
height: 'int',
lines: { type: 'list', objectType: 'LineModel' },
},
};
}
The problem with this is that I store " foreignKeys " just as properties, because there are no foreign keys in Realm ( only object references https://www.mongodb.com/docs/realm/sdk/react-native/model-data/relationships-and-embedded-objects/ ). I first have to create a child ( e.g LineChart ), and then store it's ID in it's "parent" ( DivisionComponent ). With this solution create,delete,update operations will be slow, but read will be fast. The schema design also looks a bit strange to me.
- So I asked chatgpt " Provide example of Inheritance in Realm React Native. E.g I have DivisionModel, which contains DivisionComponents. DivisionComponent could be DataTable or LineChart. ". Here is the response:
import Realm from 'realm';
// Schema for DataTable
const DataTableSchema = {
name: 'DataTable',
properties: {
// Properties specific to DataTable
// ...
},
};
// Schema for LineChart
const LineChartSchema = {
name: 'LineChart',
properties: {
// Properties specific to LineChart
// ...
},
};
// Schema for DivisionComponent (Composition)
const DivisionComponentSchema = {
name: 'DivisionComponent',
properties: {
divisionID: 'int', // Reference to parent Division
divisionComponentID: 'int',
componentType: 'string',
dataTable: 'DataTable?', // Optional reference to DataTable
lineChart: 'LineChart?', // Optional reference to LineChart
},
};
// Schema for Division
const DivisionSchema = {
name: 'Division',
primaryKey: 'divisionID',
properties: {
title: 'string',
divisionID: 'int',
components: { type: 'list', objectType: 'DivisionComponent' },
},
};
// Initialize Realm
const realm = new Realm({ schema: [DataTableSchema, LineChartSchema, DivisionComponentSchema, DivisionSchema] });
// Usage example
realm.write(() => {
const newDataTable = realm.create('DataTable', { /* properties */ });
const newLineChart = realm.create('LineChart', { /* properties */ });
const newDivisionComponent = realm.create('DivisionComponent', {
divisionID: 1,
divisionComponentID: 1,
componentType: 'DataTable',
dataTable: newDataTable,
});
const newDivision = realm.create('Division', {
title: 'Division 1',
divisionID: 1,
components: [newDivisionComponent],
});
});
First - can't call it inheritance. Secondly, while DivisionComponent holds actual reference to the " child " - he is holding reference to all possible children, where only one child will actually be set and the rest will be null. When fetching DivisionComponent for the division, I have to check which reference is not null. Currently I have 5 elements which are children of DivisionComponent -> 4 references will be null. Read will take probably longer as first approach, but still fast. Update,delete,create a bit better than first one.
- The last solution that came to my mind is more relational rather than object-oriented. The idea is that parent will not know about it's children. The division will just exist with title and divisionID. DivisionComponent will be removed completely. Elements ( e.g DataTable, LineChart and etc ) will hold reference to the parent ( Division ). Similar to what is described here: https://stackoverflow.com/a/40363017/22369836. With this approach I achieve minimal schema design overhead, actual references and fast create,write,update operations, but read is slow. I have to go to every table/object ( LineChart, DataTable... ) and ask " do you belong to this division?". This also does not sound optimal.
I am unhappy with all 3 specified approaches, as all of them have issues.
The question is: For the above described use-case and based on 3 possible approaches, what approach would you suggest and why? The suggestions are not only limited to those 3 approaches I have mentioned. I will be glad to get your own schema design proposals.