Updating an Attribute Within Your Model

This tutorial demonstrates how to update your data model in Onyx Database, including adding, removing, and changing attributes. You will learn how the database handles lightweight migrations when your model changes.

Steps to Update Your Model (Onyx Cloud Database)

1

Declare the Entities

Use the provided JSON schema to declare your entities and deploy the database using this schema definition.
1{
2      "tables": [
3        {
4          "name": "Account",
5          "identifier": {
6            "name": "accountId",
7            "type": "Int",
8            "generator": "Sequence"
9          },
10          "attributes": [
11            {
12              "name": "accountId",
13              "type": "Int"
14            },
15            {
16              "name": "accountName",
17              "type": "String"
18            },
19            {
20              "name": "balanceDue",
21              "type": "Double"
22            }
23          ],
24          "relationships": [
25            {
26              "name": "invoices",
27              "inverse": "account",
28              "inverseClass": "Invoice",
29              "type": "OneToMany",
30              "cascadePolicy": "None",
31              "fetchPolicy": "Lazy"
32            }
33          ]
34        },
35        {
36          "name": "Invoice",
37          "identifier": {
38            "name": "invoiceId",
39            "type": "Long",
40            "generator": "None"
41          },
42          "attributes": [
43            {
44              "name": "invoiceId",
45              "type": "Long"
46            },
47            {
48              "name": "invoiceDate",
49              "type": "Date"
50            },
51            {
52              "name": "dueDate",
53              "type": "Date"
54            },
55            {
56              "name": "amount",
57              "type": "Double"
58            },
59            {
60              "name": "notes",
61              "type": "String"
62            }
63          ],
64          "relationships": [
65            {
66              "name": "payments",
67              "inverse": "invoice",
68              "inverseClass": "Payment",
69              "type": "OneToOne",
70              "cascadePolicy": "Save",
71              "fetchPolicy": "Eager"
72            },
73            {
74              "name": "account",
75              "inverse": "invoices",
76              "inverseClass": "Account",
77              "type": "ManyToOne"
78            }
79          ]
80        },
81        {
82          "name": "Payment",
83          "identifier": {
84            "name": "paymentId",
85            "type": "Long",
86            "generator": "None"
87          },
88          "attributes": [
89            {
90              "name": "paymentId",
91              "type": "Long"
92            },
93            {
94              "name": "amount",
95              "type": "Double"
96            },
97            {
98              "name": "notes",
99              "type": "String"
100            }
101          ],
102          "relationships": [
103            {
104              "name": "invoice",
105              "inverse": "payments",
106              "inverseClass": "Invoice",
107              "type": "OneToOne"
108            }
109          ]
110        }
111      ],
112      "revisionDescription": "Initial schema for model updates"
113    }
  • Ensure your schema defines all required attributes, including types and relationships.
  • The identifier field is mandatory for each table and must include a unique name and a supported generator type.
  • Relationships must have a valid name and specify both an inverse property and inverseClass that refer to the corresponding related table and attribute.
2

Modify the Account Entity

Update the JSON schema to reflect changes in the Account entity, such as adding, removing, or changing attributes. Next, deploy the schema changes
1{
2      "tables": [
3        {
4          "name": "Account",
5          "identifier": {
6            "name": "accountId",
7            "type": "Long",
8            "generator": "None"
9          },
10          "attributes": [
11            {
12              "name": "accountId",
13              "type": "Long"
14            },
15            {
16              "name": "accountHolderName",
17              "type": "String"
18            },
19            {
20              "name": "accountName",
21              "type": "String"
22            }
23            // Note: Removed "balanceDue" attribute
24          ],
25          "relationships": [
26            {
27              "name": "invoices",
28              "inverse": "account",
29              "inverseClass": "Invoice",
30              "type": "OneToMany",
31              "cascadePolicy": "None",
32              "fetchPolicy": "Lazy"
33            }
34          ]
35        }
36        // ... other tables remain the same
37      ],
38      "revisionDescription": "Modified Account entity"
39    }
  • The accountHolderName attribute was added.
  • The balanceDue attribute was removed.
  • The identifier's type has been changed from Int to Long.
3

Verify New Fields

Retrieve the account using a Long rather than an Int and verify that new fields are working as expected.
1// Fetch an account. Notice that the id is now a Long rather than an Int.
2    const account = await db.findById('Account', 1);
3    console.assert(account.accountId === 1);
4
5    // The accountHolderName is a new field and is now persistable.
6    // This demonstrates that we can now take advantage of the new field.
7    account.accountHolderName = "Utility Bill";
8    await db.save('Account', account);
9
10    // Verify it was indeed persisted
11    const updatedAccount = await db.findById('Account', 1);
12    console.assert(updatedAccount.accountHolderName === "Utility Bill");
  • After saving the account, the balanceDue is no longer stored in the database since it was overwritten in the new format.

Important Notes

  • Changing attribute types is supported if the original type can be converted to the new type. You may not be able to take advantage of the lightweight migration if you were to change the type from a Long to an Int or from a String to a numeric value.
  • Removing a field does not delete the data; it still exists and is accessible through other means.
  • Adding a new field allows you to take advantage of new attributes in your model.

Troubleshooting

  • Type Conversion Errors: Ensure that the original type can be converted to the new type. For example, converting an Int to a Long is acceptable, but converting a String to a numeric type may cause issues.
  • Data Not Reflecting Changes: After modifying the model, ensure that you re-initialize the database connection and reload any entities.
  • Missing Data After Removing Fields: Remember that removing a field from your model does not delete the data from the database. The data is still there and can be accessed using lower-level APIs if necessary.

Next Steps

Now that you have learned how to update attributes within your model, you can explore more advanced topics: