react-nativerealmrealm-js

Is there a way to present One2Many Relation in correct way in realm?


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


Solution

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