Home > Software design >  Is there a way to present One2Many Relation in correct way in realm?
Is there a way to present One2Many Relation in correct way in realm?

Time:10-26

I have a very simple schema structure in my mobile app:

export const DepositSchema = {
  name: "Deposit",
  properties: {
    uuid: "string",
    payments: "Payment[]",
  },
  primaryKey: "uuid",
};

export const PaymentSchema = {
  name: Instance.Payment,
  properties: {
    payment_amount: "string",
    payment_method: "string",
    deposit: {
      type: "linkingObjects",
      objectType: "Deposit",
      property: "payments",
    },
  },
  primaryKey: "uuid",
};

So means that every deposit can have zero, one or few payments (it can be paid partially), but one payment should be assigned only to one deposit

I put Payment objects to Realm database as below:

database.manager.write(() => {
    if (payment.deposit_uuid) {
        deposit = database.manager.objectForPrimaryKey("Deposit", payment.deposit_uuid);
    }
    const createdDbPayment = database.manager.create(
        Instance.Payment,
        {
            ...payment,
            status: STATUS_TO_IGNORE,
        },
        Realm.UpdateMode.Modified,
    );
    if (deposit && createdDbPayment && deposit.payments.filtered("uuid == $0", payment.uuid).length == 0) {
        deposit.payments.push(createdDbPayment);
    }
});

Meanwhile, when i try to log payment object gotten from Realm Database it looks that instead of one deposit assigned to this payment, I got array of deposits. (ofc with only one object but it's very annoying)

The question is: Is there a way to connect this schema to present One2Many (not many2many) relationship?

I would like to achieve: payment.deposit.uuid instead of payment.deposit[0]?.uuidThanks for help

CodePudding user response:

I would like to achieve: payment.deposit.uuid instead of payment.deposit[0]?.uuid

Whenever LinkingObjects are used, they allow "automatic" navigation back to the parent object - however, they also create a many-many relationship by their nature.

That's why it's LinkingObjects (plural) not LinkingObject.

If there is only ever one to link back to, then your code will work with the index 0 being required to reference to the first element

payment.deposit[0]?.uuid

The benefit of LinkingObjects is the backlink is created for you (it's more of a calculated property than a managed property). On the other hand it's not exactly what you want.

So you'll need to create the backlink manually - and in some cases it makes more sense but you loose the 'automatic' relationship. Using pseudo-code

export const DepositSchema = {
  name: "Deposit",
  properties: {
      payments: "Payment[]"
    
export const PaymentSchema = {
  name: Payment,
  properties: {
    parent_deposit: "Deposit"

I would suggest adding a "addPayment" function to add a payment to the Deposit. When a payment is passed to the Deposit property, the parent Deposit will add its reference to the payment and then add it to the Payments List.

That will create a forward relationship from Deposits to multiple Payments and then a single backward relationship from Payment back to its parent Deposit.

Then the graph can be transversed in both directions.

  • Related