Skip to content

(DOCSP-14573): set data type #1079

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

Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e59b6ae
added set examples + bluehawked
May 13, 2021
b8be1d8
literal included set exampkes
May 13, 2021
10ef9db
added delete one set item example
May 13, 2021
ad8f25e
fix typo
May 13, 2021
b5322f9
added descriptions to set
May 13, 2021
5ddbb5f
fix grammar
May 13, 2021
62dae49
changed link + hunter to generic names
May 17, 2021
3030419
added capitalization to clearly define Realm Set as a term
May 17, 2021
179fdfc
fix wording + formatting"
May 17, 2021
e5baab5
clarified wording
May 17, 2021
1c4a3a3
fix literalincldue indentation
May 17, 2021
4a469f3
fix typo
May 17, 2021
15fbdb8
more wording fixes
May 17, 2021
81c94ad
clean up realm object model for set wording
May 17, 2021
55f6e4f
fix character names for examples
May 18, 2021
dc7d071
clarified traversal order wording
May 18, 2021
c5561b7
rst typo in <set>
May 18, 2021
5312d69
changed set to mySet
May 18, 2021
ac8a4ec
fix overview wording
May 18, 2021
cad7aec
updated overview to be more clear on differences between array
May 18, 2021
545a3c0
updated create wording
May 18, 2021
a2e8387
Update source/examples/generated/node/data-types.codeblock.remove-all…
May 19, 2021
2e37543
Update source/examples/generated/node/data-types.codeblock.remove-spe…
May 19, 2021
d6f993d
Update source/sdk/node/data-types/sets.txt
May 19, 2021
0114373
clarified that you can use spread operator to create array from set +…
May 19, 2021
5d8338d
fix grammar + wording + changed Set to Realm.Set in js snippets
May 19, 2021
b5edd4b
Fix woridng
May 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions examples/node/Examples/data-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,4 +299,92 @@ describe("Node.js Data Types", () => {
// close the realm
realm.close();
});
test("should work with the Set data type", async () => {
// :code-block-start: define-set-objects
const characterSchema = {
name: "Character",
primaryKey: "_id",
properties: {
_id: "objectId",
name: "string",
levelsCompleted: "int<>",
inventory: "string<>",
},
};
// :code-block-end:
const realm = await Realm.open({
schema: [characterSchema],
});

// :code-block-start: create-set-objects
let link, hunter;
realm.write(() => {
link = realm.create("Character", {
_id: new BSON.ObjectId(),
name: "Link",
inventory: ["elixir", "compass", "glowing shield"],
levelsCompleted: [4, 9],
});
hunter = realm.create("Character", {
_id: new BSON.ObjectId(),
name: "Hunter",
inventory: ["estus flask", "gloves", "rune"],
levelsCompleted: [1, 2, 5, 24],
});
});
// :code-block-end:

expect(link.inventory.has("elixir")).toBe(true);
expect(hunter.inventory.has("gloves")).toBe(true);

// :code-block-start: add-items-to-set
realm.write(() => {
link.inventory.add("hammer");
link.levelsCompleted.add(32);
});
// :code-block-end:

expect(link.inventory.size).toBe(4);
expect(link.levelsCompleted.size).toBe(3);

// :code-block-start: check-if-set-has-items
// check if the hunter has completed level 3 by calling the `set.has()` method
const hunterHasCompletedLevelThree = hunter.levelsCompleted.has(3);
console.log(
`Is level three completed by the hunter: ${hunterHasCompletedLevelThree}`
);
// :code-block-end:
expect(hunterHasCompletedLevelThree).toBe(false);

// :code-block-start: remove-specific-item-from-set
realm.write(() => {
// remove the compass from link's inventory by calling `set.delete()` within a write transaction
link.inventory.delete("compass");
});

// :code-block-end:
expect(link.inventory.has("compass")).toBe(false);

// :code-block-start: remove-all-items-from-set
realm.write(() => {
// clear all data from the inventory slot of the hunter by calling `set.clear()` in a write transaction
hunter.inventory.clear();
});
// :code-block-end:

// :code-block-start: check-set-size
// check how many items the hunter has in his inventory through the `set.size` property
const hunterInventorySize = hunter.inventory.size;
console.log(`The hunter has ${hunterInventorySize} inventory items`);
// :code-block-end:
expect(hunter.inventory.size).toBe(0);

// delete the object specifically created in this test to keep tests idempotent
realm.write(() => {
realm.delete(link);
realm.delete(hunter);
});
// close the realm
realm.close();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
realm.write(() => {
link.inventory.add("hammer");
link.levelsCompleted.add(32);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// check if the hunter has completed level 3 by calling the `set.has()` method
const hunterHasCompletedLevelThree = hunter.levelsCompleted.has(3);
console.log(
`Is level three completed by the hunter: ${hunterHasCompletedLevelThree}`
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// check how many items the hunter has in his inventory through the `set.size` property
const hunterInventorySize = hunter.inventory.size;
console.log(`The hunter has ${hunterInventorySize} inventory items`);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
let link, hunter;
realm.write(() => {
link = realm.create("Character", {
_id: new BSON.ObjectId(),
name: "Link",
inventory: ["elixir", "compass", "glowing shield"],
levelsCompleted: [4, 9],
});
hunter = realm.create("Character", {
_id: new BSON.ObjectId(),
name: "Hunter",
inventory: ["estus flask", "gloves", "rune"],
levelsCompleted: [1, 2, 5, 24],
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const characterSchema = {
name: "Character",
primaryKey: "_id",
properties: {
_id: "objectId",
name: "string",
levelsCompleted: "int<>",
inventory: "string<>",
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
realm.write(() => {
// clear all data from the inventory slot of the hunter by calling `set.clear()` in a write transaction
hunter.inventory.clear();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
realm.write(() => {
// remove the compass from link's inventory by calling `set.delete()` within a write transaction
link.inventory.delete("compass");
});

86 changes: 85 additions & 1 deletion source/sdk/node/data-types/sets.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,88 @@ Sets - Node.js SDK
.. versionadded:: 10.5.0-beta.1

Overview
--------
--------
A {+service-short+} set is a special object that allows you to store a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should make it conspicuous that "Realm Set" is a term, either through capitalization similar to Javascript "Set" or using a bold format.
After reading the first couple of paragraphs, I'm also curious as to whether you can use Javascript Sets instead, or if I can only use Realm Sets since the title of the page is Sets.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree: A Realm Set is not a 1:1 mapping of a JavaScript Set (but heavily inspired by it).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point, I've altered it to be "Realm Set" consistently throughout the doc to indicate it is a term.

As for indicating that it is not a 1:1 mapping, I've included the line: "Realm sets work similarly to JavaScript Sets, except they must be a single type and can only be modified within a write-transaction"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"special object" sounds weird and doesn't really tel us anything. Since everyone is familiar with Arrays, perhaps a start like this?

A {+service-short+} set is an object that stores a collection of values. A Set is similar to an Array, except:

  • Each value in a Set must be unique,
  • Arrays are ordered by index, while sets are iterable and unordered (this isn't quite right...)

Copy link
Contributor Author

@mohammadhunan-dev mohammadhunan-dev May 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm down for being a bit clearer on the advantages of Set. I do want to keep it a bit more subtle and not necessarily bring up array for the following reasons:

  • JavaScript developers should probably know the differences between set and array. Explaining the differences between the two would be explaining JS, not explaining how to use Realm with JS. For those that aren't familiar with the differences, I've linked out to the mdn docs on set.

As for showing when to use set, I've added some info in the intro, the new intro reads:

"A Realm Set is a special object that allows you to store a collection of unique values. Realm Sets are based on JavaScript Sets, but can only contain values of a single type and can only be modified within a write transaction. Sets allow you to perform math operations such as finding the union, intersection, or difference between two sets. To learn more about performing these operations, see the MDN docs for Implementing basic set operations."

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JS Set does not currently support the math operations. Its implementation has been kept as close as possible to JS's own set type.

collection of unique values. {+service-short+} sets work similarly to JavaScript
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sets work similarly to JavaScript
to
sets are based on JavaScript Sets, but are limited to a single value type and can only be modified...

Copy link
Contributor Author

@mohammadhunan-dev mohammadhunan-dev May 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

took this suggestion almost verbatim 👍

:mdn:`Sets <Web/JavaScript/Reference/Global_Objects/Set>`, except they must be a single
type and can only be modified within a write-transaction.

.. note:: {+service-short+} Sets Do Not Guarantee Traversal Order

When using a ``forEach()`` loop or other :mdn:`iteration methods
<Web/JavaScript/Reference/Global_Objects/Set#iteration_methods>` to iterate
through a loop, {+service-short+} sets may be in a different order than
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

through a loop,
to
through a set,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the sentence to: "When using a forEach() loop or other iteration method to traverse the set in a loop, the content of the Realm Set may be in a different order than originally written to."

originally written to. If you require an ordered version of your set, you
must implement that order yourself. You can do this by creating an array of
the set's values in the insertion order.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last sentence here is confusing. Are you saying the user should create an Array that gets updated every time the set is updated, and insert into the array in the order I want?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially, that's it. I've altered it to be a bit clearer:

"You can do this by creating an array from the set, using Array.from(mySet), and updating that array when the set has been modified through a change listener."


.. _node-define-set-objects:

Realm Object Models
-------------------
To define a property's values as a {+service-short+} set, specify the data type
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be shortened to:

To define a property type as a Set, specify the data type you want in the set, followed by <>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works, fixed now 👍

followed by a less than and equal sign. For instance, for a set made of integer
values, specify ``"int<>"``.

.. literalinclude:: /examples/generated/node/data-types.codeblock.define-set-objects.js
:language: javascript

.. _node-create-set-objects:

Create an Object With a Set
---------------------------
To create an object with a property that value is of the set data type, create a
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording here is confusing me.
Does this work?

To create an object that has one or more set properties, you must create the object within a write transaction. You then initialize the set-type properties as you would an array, by passing the initial values in brackets ([])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a combo of the two phrasings:

"To create an object with a {+service-short+} Set property, you must create the object within a write transaction. When defining your Realm object, initialize the set by passing an empty array or an array with your initial values."

{+service-short+} object within a write transaction. When defining your
{+service-short+} object, specify your set property's value as an array of
initial values.

.. literalinclude:: /examples/generated/node/data-types.codeblock.create-set-objects.js
:language: javascript


.. _node-add-items-to-set:

Add Items to a Set
------------------
To add items to a set, pass the new value to the ``set.add()`` method within a write transaction.

.. literalinclude:: /examples/generated/node/data-types.codeblock.add-items-to-set.js
:language: javascript

.. _node-check-if-set-has-items:

Check if a Set has Specific Items
---------------------------------
To find out if a set has a particular value, pass the value to the ``set.has()`` method. The
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider changing "To find out" to "To determine"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

``set.has()`` method will return true if the set contains the value specified.

.. literalinclude:: /examples/generated/node/data-types.codeblock.check-if-set-has-items.js
:language: javascript

.. _node-check-set-size:

Check the Size of a Set
-----------------------
To discover how many items are in a set, you can check the set's ``size`` property.

.. literalinclude:: /examples/generated/node/data-types.codeblock.check-set-size.js
:language: javascript

.. _node-remove-specific-item-from-set:

Remove an Item from a Set
-------------------------
To remove a specific value from a set, pass the value to the ``set.delete()`` method within a write transaction.

.. literalinclude:: /examples/generated/node/data-types.codeblock.remove-specific-item-from-set.js
:language: javascript


.. _node-remove-all-items-from-set:

Remove all Items from a Set
---------------------------
To clear the set, run the ``set.clear()`` method within a write transaction.

.. literalinclude:: /examples/generated/node/data-types.codeblock.remove-all-items-from-set.js
:language: javascript