diff --git a/examples/node/Examples/data-types.js b/examples/node/Examples/data-types.js index dd899119fe..da25932bb6 100644 --- a/examples/node/Examples/data-types.js +++ b/examples/node/Examples/data-types.js @@ -1,4 +1,128 @@ import Realm from "realm"; +import BSON from "bson"; +// :code-block-start: define-embedded-objects +const AddressSchema = { + name: "Address", + embedded: true, // default: false + properties: { + street: "string?", + city: "string?", + country: "string?", + postalCode: "string?", + }, +}; + +const ContactSchema = { + name: "Contact", + primaryKey: "_id", + properties: { + _id: "objectId", + name: "string", + address: "Address", // Embed a single object + }, +}; + +const BusinessSchema = { + name: "Business", + primaryKey: "_id", + properties: { + _id: "objectId", + name: "string", + addresses: { type: "list", objectType: "Address" }, // Embed an array of objects + }, +}; +// :code-block-end: describe("Node.js Data Types", () => { -}) \ No newline at end of file + test("should create and read and delete an embedded object", async () => { + const realm = await Realm.open({ + schema: [AddressSchema, ContactSchema], + }); + + // :code-block-start: create-an-embedded-object + // create an embedded address object + const sydneyOrthodontics = { + street: "42 Wallaby Way", + city: "Sydney", + country: "Australia", + postalCode: "2774", + }; + realm.write(() => { + // create a contact object + realm.create("Contact", { + _id: new BSON.ObjectId(), + name: "Philip Sherman", + address: sydneyOrthodontics, // embed the address in the contact object + }); + }); + // :code-block-end: + + // :code-block-start: query-an-embedded-object + const philipShermanAddress = realm + .objects("Contact") + .filtered("name = 'Philip Sherman'")[0].address.street; + console.log(`Philip Sherman's address is ${philipShermanAddress}`); + // :code-block-end: + expect(philipShermanAddress).toBe("42 Wallaby Way"); // this assertion tests both the 'query-an-embedded-object' and 'create-an-embedded-object' code blocks + + // // :code-block-start: delete-an-embedded-object + realm.write(() => { + // Deleting the contact will delete the embedded address of that contact + realm.delete( + realm.objects("Contact").filtered("name = 'Philip Sherman'") + ); + }); + // :code-block-end: + + // close the realm + realm.close(); + }); + // update and delete an embedded object + test("should update and overwrite an embedded object", async () => { + const realm = await Realm.open({ + schema: [AddressSchema, ContactSchema], + }); + const harryAddress = { + street: "4 Privet Drive", + city: "Little Whinging, Surrey", + country: "UK", + postalCode: "WD4 8PN", + }; + realm.write(() => { + realm.create("Contact", { + _id: new BSON.ObjectId(), + name: "Harry Potter", + address: harryAddress, + }); + }); + + // :code-block-start: update-an-embedded-object + // Find the contact with the address you want to update + const harryPotter = realm + .objects("Contact") + .filtered("name = 'Harry Potter'")[0]; + // modify the property of the embedded object in a write transaction + realm.write(() => { + // update the embedded object directly through the contact + harryPotter.address.street = "1 Hogwarts Ave"; + }); + // :code-block-end: + expect(harryPotter.address.street).toBe("1 Hogwarts Ave"); + + // :code-block-start: overwrite-an-embedded-object + // create a new address + const harryNewAddress = { + street: "12 Grimmauld Place", + city: "London", + country: "UK", + postalCode: "E1 7AA", + }; + realm.write(() => { + // overwrite the embedded object with the new address within a write transaction + harryPotter.address = harryNewAddress; + }); + // :code-block-end: + + expect(harryPotter.address.city).toBe("London"); + }); +}); diff --git a/source/examples/generated/node/data-types.codeblock.create-an-embedded-object.js b/source/examples/generated/node/data-types.codeblock.create-an-embedded-object.js new file mode 100644 index 0000000000..90e3da5afa --- /dev/null +++ b/source/examples/generated/node/data-types.codeblock.create-an-embedded-object.js @@ -0,0 +1,15 @@ +// create an embedded address object +const sydneyOrthodontics = { + street: "42 Wallaby Way", + city: "Sydney", + country: "Australia", + postalCode: "2774", +}; +realm.write(() => { + // create a contact object + realm.create("Contact", { + _id: new BSON.ObjectId(), + name: "Philip Sherman", + address: sydneyOrthodontics, // embed the address in the contact object + }); +}); diff --git a/source/examples/generated/node/data-types.codeblock.define-embedded-objects.js b/source/examples/generated/node/data-types.codeblock.define-embedded-objects.js new file mode 100644 index 0000000000..7e5cc09651 --- /dev/null +++ b/source/examples/generated/node/data-types.codeblock.define-embedded-objects.js @@ -0,0 +1,30 @@ +const AddressSchema = { + name: "Address", + embedded: true, // default: false + properties: { + street: "string?", + city: "string?", + country: "string?", + postalCode: "string?", + }, +}; + +const ContactSchema = { + name: "Contact", + primaryKey: "_id", + properties: { + _id: "objectId", + name: "string", + address: "Address", // Embed a single object + }, +}; + +const BusinessSchema = { + name: "Business", + primaryKey: "_id", + properties: { + _id: "objectId", + name: "string", + addresses: { type: "list", objectType: "Address" }, // Embed an array of objects + }, +}; diff --git a/source/examples/generated/node/data-types.codeblock.delete-an-embedded-object.js b/source/examples/generated/node/data-types.codeblock.delete-an-embedded-object.js new file mode 100644 index 0000000000..48f719d4f8 --- /dev/null +++ b/source/examples/generated/node/data-types.codeblock.delete-an-embedded-object.js @@ -0,0 +1,6 @@ +realm.write(() => { + // Deleting the contact will delete the embedded address of that contact + realm.delete( + realm.objects("Contact").filtered("name = 'Philip Sherman'") + ); +}); diff --git a/source/examples/generated/node/data-types.codeblock.overwrite-an-embedded-object.js b/source/examples/generated/node/data-types.codeblock.overwrite-an-embedded-object.js new file mode 100644 index 0000000000..50960d315b --- /dev/null +++ b/source/examples/generated/node/data-types.codeblock.overwrite-an-embedded-object.js @@ -0,0 +1,11 @@ +// create a new address +const harryNewAddress = { + street: "12 Grimmauld Place", + city: "London", + country: "UK", + postalCode: "E1 7AA", +}; +realm.write(() => { + // overwrite the embedded object with the new address within a write transaction + harryPotter.address = harryNewAddress; +}); diff --git a/source/examples/generated/node/data-types.codeblock.query-an-embedded-object.js b/source/examples/generated/node/data-types.codeblock.query-an-embedded-object.js new file mode 100644 index 0000000000..14657f0bcc --- /dev/null +++ b/source/examples/generated/node/data-types.codeblock.query-an-embedded-object.js @@ -0,0 +1,4 @@ +const philipShermanAddress = realm + .objects("Contact") + .filtered("name = 'Philip Sherman'")[0].address.street; +console.log(`Philip Sherman's address is ${philipShermanAddress}`); diff --git a/source/examples/generated/node/data-types.codeblock.update-an-embedded-object.js b/source/examples/generated/node/data-types.codeblock.update-an-embedded-object.js new file mode 100644 index 0000000000..02680cc8dd --- /dev/null +++ b/source/examples/generated/node/data-types.codeblock.update-an-embedded-object.js @@ -0,0 +1,9 @@ +// Find the contact with the address you want to update +const harryPotter = realm + .objects("Contact") + .filtered("name = 'Harry Potter'")[0]; +// modify the property of the embedded object in a write transaction +realm.write(() => { + // update the embedded object directly through the contact + harryPotter.address.street = "1 Hogwarts Ave"; +}); diff --git a/source/sdk/node/data-types/embedded-objects.txt b/source/sdk/node/data-types/embedded-objects.txt index c1ff8fd4cb..f807b0f465 100644 --- a/source/sdk/node/data-types/embedded-objects.txt +++ b/source/sdk/node/data-types/embedded-objects.txt @@ -11,3 +11,110 @@ Embedded Objects - Node.js SDK :backlinks: none :depth: 2 :class: singlecol + +Overview +-------- + +An embedded object is a special type of :ref:`Realm object ` +that models complex data about a specific object. Embedded objects are similar +to :ref:`relationships `, but they provide additional +constraints and map more naturally to the denormalized :manual:`MongoDB document +model `. + +Realm enforces unique ownership constraints that treat each embedded object as +nested data inside a single, specific parent object. An embedded object +inherits the lifecycle of its parent object and cannot exist as an independent +Realm object. This means that embedded objects cannot have a primary key and +that Realm automatically deletes embedded objects if their parent object is +deleted. + +.. tip:: Embedded object types are reusable and composable + + You can use the same embedded object type in multiple parent object types, and + you can embed objects inside other embedded objects. You can even + recursively reference an embedded object type as an optional property in its + own definition. + +.. note:: Realm Uses Cascading Deletes for Embedded Objects + + When you delete a Realm object, Realm automatically deletes any + embedded objects referenced by that object. Any objects that your + application must persist after the deletion of their parent object + should use :ref:`relationships ` + instead. + +Realm Object Models +~~~~~~~~~~~~~~~~~~~ + +To define an embedded object, set ``embedded`` +to ``true``. You can reference an embedded object type from parent object types +in the same way as you would define a relationship: + +.. important:: + + Embedded objects cannot have a :ref:`primary key `. + +.. literalinclude:: /examples/generated/node/data-types.codeblock.define-embedded-objects.js + :language: javascript + :emphasize-lines: 3, 18, 28 + + +JSON Schema +~~~~~~~~~~~ + +.. include:: /includes/embedded-object-json-schema.rst + + +Read and Write Embedded Objects +------------------------------- + +Create an Embedded Object +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To create an embedded object, assign an instance of the embedded object +to a parent object's property: + +.. literalinclude:: /examples/generated/node/data-types.codeblock.create-an-embedded-object.js + :language: javascript + +Update an Embedded Object Property +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To update a property in an embedded object, modify the property in a +write transaction: + +.. literalinclude:: /examples/generated/node/data-types.codeblock.update-an-embedded-object.js + :language: javascript + + +Overwrite an Embedded Object +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To overwrite an embedded object, reassign the embedded object property +of a party to a new instance in a write transaction: + +.. literalinclude:: /examples/generated/node/data-types.codeblock.overwrite-an-embedded-object.js + :language: javascript + + +Query a Collection on Embedded Object Properties +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use dot notation to filter or sort a :ref:`collection +` of objects based on an embedded object +property value: + +.. include:: /includes/directly-query-embedded-objects-note.rst + +.. literalinclude:: /examples/generated/node/data-types.codeblock.query-an-embedded-object.js + :language: javascript + + + +Delete an Embedded Object +~~~~~~~~~~~~~~~~~~~~~~~~~ +Realm Uses Cascading Deletes for Embedded Objects. To delete an embedded object, +delete the embedded object's parent. + +.. literalinclude:: /examples/generated/node/data-types.codeblock.delete-an-embedded-object.js + :language: javascript diff --git a/source/sdk/node/fundamentals/relationships-and-embedded-objects.txt b/source/sdk/node/fundamentals/relationships-and-embedded-objects.txt index 6307b993a0..b3017716fb 100644 --- a/source/sdk/node/fundamentals/relationships-and-embedded-objects.txt +++ b/source/sdk/node/fundamentals/relationships-and-embedded-objects.txt @@ -175,62 +175,6 @@ to :ref:`relationships `, but they provide additional constraints and map more naturally to the denormalized :manual:`MongoDB document model `. -Realm enforces unique ownership constraints that treat each embedded object as -nested data inside of a single, specific parent object. An embedded object -inherits the lifecycle of its parent object and cannot exist as an independent -Realm object. This means that embedded objects cannot have a primary key and -that Realm automatically deletes embedded objects if their parent object is -deleted. - -.. tip:: Embedded object types are reusable and composable - - You can use the same embedded object type in multiple parent object types and - you can embed objects inside of other embedded objects. You can even - recursively reference an embedded object type as an optional property in its - own definition. - -Realm Object Models -~~~~~~~~~~~~~~~~~~~ - -To specify that a Realm object model define an embedded object, set ``embedded`` -to ``true``. You can reference an embedded object type from parent object types -in the same way as you would define a relationship: - -.. code-block:: javascript - :emphasize-lines: 3, 18, 28 - - const AddressSchema = { - name: "Address", - embedded: true, // default: false - properties: { - street: "string?", - city: "string?", - country: "string?", - postalCode: "string?", - }, - }; - - const ContactSchema = { - name: "Contact", - primaryKey: "_id", - properties: { - _id: "objectId", - name: "string", - address: "Address", // Embed a single object - }, - }; - - const BusinessSchema = { - name: "Business", - primaryKey: "_id", - properties: { - _id: "objectId", - name: "string", - addresses: { type: "list", objectType: "Address" }, // Embed an array of objects - }, - }; - -JSON Schema -~~~~~~~~~~~ - -.. include:: /includes/embedded-object-json-schema.rst +Learn more about :doc:`Embedded objects +`, including how to read and write +embedded objects. \ No newline at end of file