Skip to content

Commit

Permalink
(DOCSP-15613): Node.js embedded objects type (#1047)
Browse files Browse the repository at this point in the history
* Added documentation of Node.js embedded objects under data types

* clean up relationships and embedded objects

* added CRUD examples for embedded obj

* added bluehawked examples

* fix rst syntax highlight + add description for deletes

* Update source/sdk/node/data-types/embedded-objects.txt

* Update source/sdk/node/data-types/embedded-objects.txt

* Update source/sdk/node/data-types/embedded-objects.txt

* Update source/sdk/node/data-types/embedded-objects.txt

* Update source/sdk/node/data-types/embedded-objects.txt

Co-authored-by: Mohammad Hunan Chughtai <[email protected]>
  • Loading branch information
Mohammad Hunan Chughtai and Mohammad Hunan Chughtai authored May 11, 2021
1 parent 2755206 commit b79ffbc
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 60 deletions.
126 changes: 125 additions & 1 deletion examples/node/Examples/data-types.js
Original file line number Diff line number Diff line change
@@ -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", () => {
})
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");
});
});
Original file line number Diff line number Diff line change
@@ -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
});
});
Original file line number Diff line number Diff line change
@@ -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
},
};
Original file line number Diff line number Diff line change
@@ -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'")
);
});
Original file line number Diff line number Diff line change
@@ -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;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const philipShermanAddress = realm
.objects("Contact")
.filtered("name = 'Philip Sherman'")[0].address.street;
console.log(`Philip Sherman's address is ${philipShermanAddress}`);
Original file line number Diff line number Diff line change
@@ -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";
});
107 changes: 107 additions & 0 deletions source/sdk/node/data-types/embedded-objects.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 <node-object-schemas>`
that models complex data about a specific object. Embedded objects are similar
to :ref:`relationships <node-client-relationships>`, but they provide additional
constraints and map more naturally to the denormalized :manual:`MongoDB document
model </core/data-modeling-introduction/>`.

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 <node-client-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 <node-primary-keys>`.

.. 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
<node-results-collections>` 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
Original file line number Diff line number Diff line change
Expand Up @@ -175,62 +175,6 @@ to :ref:`relationships <node-client-relationships>`, but they provide additional
constraints and map more naturally to the denormalized :manual:`MongoDB document
model </core/data-modeling-introduction/>`.

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
</sdk/node/data-types/embedded-objects>`, including how to read and write
embedded objects.

0 comments on commit b79ffbc

Please sign in to comment.