-
Notifications
You must be signed in to change notification settings - Fork 89
(DOCSP-15613): Node.js embedded objects type #1047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
5bab40e
2511b65
3ea0b70
701f1e5
69316ab
995556e
e2584ba
59865bd
66bfaac
efdd888
3806bff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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"; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 of other embedded objects. You can even | ||
mohammadhunan-dev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
recursively reference an embedded object type as an optional property in its | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm kind of fascinated by the idea of recursively referencing an embedded object type as an optional property in its own definition, but am having trouble visualizing a use case for it. I wonder if this might be a good example to add to the page? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might look something like:
Though that tip is copied over from the existing docs, and is a scenario we probably don't want to actually show in our docs since it's so unique that I can't think of a practical use-case. The tip does show the sheer flexibility of embedded objects though. |
||
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 specify that a Realm object model define an embedded object, set ``embedded`` | ||
mohammadhunan-dev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 objects parent. | ||
mohammadhunan-dev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
.. literalinclude:: /examples/generated/node/data-types.codeblock.delete-an-embedded-object.js | ||
:language: javascript |
Uh oh!
There was an error while loading. Please reload this page.