How to reflect inheritance in Realm React Native JS?

73 views Asked by At

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 ).

  1. 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.

  1. 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.

  1. 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.

0

There are 0 answers