New in version realm@10.5.0.
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.
Realm Object Models
You can define a Realm object model property type as a Realm Set, in a two ways:
Specify the data type the Set will contain, followed by
<>.Use object notation and the
typefield for more complicated properties.
1 class Character extends Realm.Object { 2 static schema = { 3 name: 'Character', 4 primaryKey: '_id', 5 properties: { 6 _id: 'objectId', 7 name: 'string', 8 levelsCompleted: 'int<>', 9 inventory: { 10 type: 'set', 11 objectType: 'string', 12 }, 13 }, 14 }; 15 }
1 class Character extends Realm.Object<Character> { 2 _id!: Realm.BSON.ObjectId; 3 name!: string; 4 levelsCompleted!: Realm.Set<number>; 5 inventory!: Realm.Set<string>; 6 7 static schema: ObjectSchema = { 8 name: 'Character', 9 primaryKey: '_id', 10 properties: { 11 _id: 'objectId', 12 name: 'string', 13 levelsCompleted: 'int<>', 14 inventory: { 15 type: 'set', 16 objectType: 'string', 17 }, 18 }, 19 }; 20 }
Create an Object With a Set
To create an object with a Realm Set property, you must create the object within a write transaction. When defining your Realm object, initialize the Realm Set by passing an empty array or an array with your initial values.
Example
In the following example of a CreateInitialCharacters component, we create
Character objects with Set properties.
The CreateInitialCharacters component does the following:
Gets access to an opened realm instance by calling the
useRealm()hook within the component.Uses React's useEffect hook to call an anonymous function only once with
useEffectand an empty dependency array. Within the anonymous function, we create two differentCharacterobjects within a write transaction. We set each character'sinventoryandlevelsCompletedsets as an array with initial values.Retrieves all characters in the realm instance by passing the
Characterclass to theuseQuery()hook.Displays each character's name in the UI as a
Textelement.
1 const CreateInitialCharacters = () => { 2 const realm = useRealm(); 3 useEffect(() => { 4 realm.write(() => { 5 realm.create('Character', { 6 _id: new Realm.BSON.ObjectId(), 7 name: 'AdventurousPlayer', 8 inventory: ['elixir', 'compass', 'glowing shield'], 9 levelsCompleted: [4, 9], 10 }); 11 }); 12 realm.write(() => { 13 realm.create('Character', { 14 _id: new Realm.BSON.ObjectId(), 15 name: 'HealerPlayer', 16 inventory: ['estus flask', 'gloves', 'rune'], 17 levelsCompleted: [1, 2, 5, 24], 18 }); 19 }); 20 }, []); 21 const characters = useQuery(Character); 22 23 return ( 24 <View> 25 {characters.map(character => ( 26 <View key={character._id}> 27 <Text>{character.name}</Text> 28 </View> 29 ))} 30 </View> 31 ); 32 };
1 const CreateInitialCharacters = () => { 2 const realm = useRealm(); 3 useEffect(() => { 4 realm.write(() => { 5 realm.create('Character', { 6 _id: new Realm.BSON.ObjectId(), 7 name: 'AdventurousPlayer', 8 inventory: ['elixir', 'compass', 'glowing shield'], 9 levelsCompleted: [4, 9], 10 }); 11 }); 12 13 realm.write(() => { 14 realm.create('Character', { 15 _id: new Realm.BSON.ObjectId(), 16 name: 'HealerPlayer', 17 inventory: ['estus flask', 'gloves', 'rune'], 18 levelsCompleted: [1, 2, 5, 24], 19 }); 20 }); 21 }, []); 22 const characters = useQuery(Character); 23 24 return ( 25 <View> 26 {characters.map(character => ( 27 <View key={character._id}> 28 <Text>{character.name}</Text> 29 </View> 30 ))} 31 </View> 32 ); 33 };
Add Items to a Set
To add an item to a Set, pass the new value to the Realm.Set.add() method method within a write transaction.
Example
In the following example of a AddInventoryToCharacter component, we add new
Set elements to the character's inventory.
The AddInventoryToCharacter component does the following:
Gets access to an opened realm instance by calling the
useRealm()hook within the component.Creates a state variable called "inventoryItem" that represents the new inventory item to add to the inventory Set.
Retrieves the character by passing the
Characterclass to theuseQuery()hook and running the Collection.filtered() method on the result to filter for characters with the name matching thecharacterNameprop. Then we set the variablecharacterto the first matching result.Creates a component method
addInventoryItem()that performs a write transaction that adds an inventory item to the character's inventory by passing theinventoryItemstate variable toRealm.Set.add().Renders a
TextInputthat changes theinventoryItemstate variable, and aButtonthat calls theaddInventoryItem()method.
1 const AddInventoryToCharacter = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const character = useQuery( 5 Character, 6 characters => { 7 return characters.filtered(`name = '${characterName}'`); 8 }, 9 [characterName], 10 )[0]; 11 12 const addInventoryItem = () => { 13 realm.write(() => { 14 character?.inventory.add(inventoryItem); 15 }); 16 }; 17 18 return ( 19 <View> 20 <TextInput 21 onChangeText={text => setInventoryItem(text)} 22 value={inventoryItem} 23 /> 24 <Button 25 title='Add Inventory Item' 26 onPress={addInventoryItem} 27 /> 28 </View> 29 ); 30 };
1 const AddInventoryToCharacter = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState(''); 8 const character = useQuery( 9 Character, 10 characters => { 11 return characters.filtered(`name = '${characterName}'`); 12 }, 13 [characterName], 14 )[0]; 15 16 const addInventoryItem = () => { 17 realm.write(() => { 18 character?.inventory.add(inventoryItem); 19 }); 20 }; 21 22 return ( 23 <View> 24 <TextInput 25 onChangeText={text => setInventoryItem(text)} 26 value={inventoryItem} 27 /> 28 <Button 29 title='Add Inventory Item' 30 onPress={addInventoryItem} 31 /> 32 </View> 33 ); 34 };
Check if a Set has Specific Items and Check the Size of a Set
You may want to check for information about your Set, such as its size or if it contains specific item.
To determine if a Set contains a particular value, pass the value to the
Realm.Set.has() method. This method will return
true if the Set contains the value specified.
To discover how many items are in a Set, you can check its size property.
Example
In the following example of a QueryCharacterInventory component, we check
the character's inventory size and if it has a specific item.
The QueryCharacterInventory component does the following:
Creates a state variable called "inventoryItem" that represents the inventory item that you want to search the character's inventory for.
Uses the
useQueryhook to perform a query for all characters, and filter the results to only include the characters with the name matching thecharacterNamepassed to the component as a prop. Then we get the first matching result.Retrieves the character by passing the
Characterclass to theuseQuery()hook and running the Collection.filtered() method on the result to filter for characters with the name matching thecharacterNameprop. Then we set the variablecharacterto the first matching result.Creates a component method
queryCharacterInventorythat passes theinventoryItemstate variable toRealm.Set.has()to check if the character's inventory contains the item. If the character's inventory contains the item, the method alerts that the character has the item. If the character's inventory does not contain the item, the method alerts that the character does not have the item.Renders the character's name, and renders the inventory size using the
sizeproperty of the character's inventory. It also renders aTextInputthat changes theinventoryItemstate variable, and aButtonthat calls thequeryCharacterInventorymethod.
1 const QueryCharacterInventory = ({characterName}) => { 2 const [inventoryItem, setInventoryItem] = useState(''); 3 const character = useQuery( 4 Character, 5 characters => { 6 return characters.filtered(`name = '${characterName}'`); 7 }, 8 [characterName], 9 )[0]; 10 11 const queryCharacterInventory = () => { 12 const characterDoesHaveItem = character.inventory.has(inventoryItem); 13 if (characterDoesHaveItem) { 14 Alert.alert(`Character has item: ${inventoryItem}`); 15 } else { 16 Alert.alert(`Item not found in character's inventory`); 17 } 18 }; 19 return ( 20 <View> 21 <Text>{character.name}</Text> 22 <Text> 23 Total number of inventory items: {character.inventory.size} 24 </Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Query for Inventory' 31 onPress={queryCharacterInventory} 32 /> 33 </View> 34 ); 35 };
1 const QueryCharacterInventory = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const [inventoryItem, setInventoryItem] = useState(''); 7 const character = useQuery( 8 Character, 9 characters => { 10 return characters.filtered(`name = '${characterName}'`); 11 }, 12 [characterName], 13 )[0]; 14 15 const queryCharacterInventory = () => { 16 const characterDoesHaveItem: Boolean = 17 character.inventory.has(inventoryItem); 18 if (characterDoesHaveItem) { 19 Alert.alert(`Character has item: ${inventoryItem}`); 20 } else { 21 Alert.alert(`Item not found in character's inventory`); 22 } 23 }; 24 return ( 25 <View> 26 <Text>{character.name}</Text> 27 <Text> 28 Total number of inventory items: {character.inventory.size} 29 </Text> 30 <TextInput 31 onChangeText={text => setInventoryItem(text)} 32 value={inventoryItem} 33 /> 34 <Button 35 title='Query for Inventory' 36 onPress={queryCharacterInventory} 37 /> 38 </View> 39 ); 40 };
Remove Set Information
You may want to remove a specific item or all items from a Set.
To remove a specific value from a Set, pass the value to the Realm.Set.delete() method within a write transaction.
To clear the Set, run the Realm.Set.clear() method within a write transaction.
Example
In the following example of a RemoveInventoryFromCharacter component, we
remove a specific item from the Set and clear the Set of all items.
The RemoveInventoryFromCharacter component does the following:
Gets access to an opened realm instance by calling the
useRealm()hook within the component.Creates a state variable called "inventoryItem" that represents the inventory item to remove from the inventory Set.
Creates a component method
removeInventoryItemthat passes theinventoryItemstate variable toRealm.Set.delete()to remove the item from the character's inventory.Creates a component method
removeAllInventorythat callsRealm.Set.clear()to remove all items from the character's inventory.Renders a
TextInputthat changes theinventoryItemstate variable, and twoButtoncomponents that call theremoveInventoryItemandremoveAllInventorymethods, respectively.
1 const RemoveInventoryFromCharacter = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const character = useQuery( 5 Character, 6 characters => { 7 return characters.filtered(`name = '${characterName}'`); 8 }, 9 [characterName], 10 )[0]; 11 12 const removeInventoryItem = () => { 13 realm.write(() => { 14 character?.inventory.delete(inventoryItem); 15 }); 16 }; 17 const removeAllInventory = () => { 18 realm.write(() => { 19 character?.inventory.clear(); 20 }); 21 }; 22 return ( 23 <View> 24 <Text>{character.name}</Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Remove Inventory Item' 31 onPress={removeInventoryItem} 32 /> 33 <Button 34 title='Remove All Inventory' 35 onPress={removeAllInventory} 36 /> 37 </View> 38 ); 39 };
1 const RemoveInventoryFromCharacter = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState(''); 8 const character = useQuery( 9 Character, 10 characters => { 11 return characters.filtered(`name = '${characterName}'`); 12 }, 13 [characterName], 14 )[0]; 15 16 const removeInventoryItem = () => { 17 realm.write(() => { 18 character?.inventory.delete(inventoryItem); 19 }); 20 }; 21 const removeAllInventory = () => { 22 realm.write(() => { 23 character?.inventory.clear(); 24 }); 25 }; 26 return ( 27 <View> 28 <Text>{character.name}</Text> 29 <TextInput 30 onChangeText={text => setInventoryItem(text)} 31 value={inventoryItem} 32 /> 33 <Button 34 title='Remove Inventory Item' 35 onPress={removeInventoryItem} 36 /> 37 <Button 38 title='Remove All Inventory' 39 onPress={removeAllInventory} 40 /> 41 </View> 42 ); 43 };
Traverse a Set
You can traverse a Set to access each item in the Set. To traverse a
Set, use the Set.map() method or alternative iteration
method.
However, by default the order of the items in a Set is not guaranteed. To traverse a Set in order, you can store the Set's items in a state variable and update that state variable when you add new items to the Set.
Example
In the following example of a TraverseCharacterInventory component, a
character starts with no inventory items. When the user adds items to the
inventory Set, the component displays each item in the Set in both an
ordered and unordered list.
The TraverseCharacterInventory component does the following:
Gets access to an opened realm instance by calling the
useRealm()hook within the component.Creates a state variable called "inventoryItem" that represents the new inventory item to add to the inventory Set.
Creates a state variable called "inventory" that will hold the character's inventory items in order of insertion.
Retrieves the character by passing the
Characterclass to theuseQuery()hook and running the Collection.filtered() method on the result to filter for characters with the name matching thecharacterNameprop. Then we set the variablecharacterto the first matching result.Creates a component method
addInventoryItem()that performs a write transaction that adds an inventory item to the character's inventory by passing theinventoryItemstate variable to the Realm.Set.add() method. After the write transaction, the method adds theinventoryItemto theinventoryarray state variable.Renders a
TextInputthat changes theinventoryItemstate variable, and aButtonthat calls theaddInventoryItem()method.Renders a list of the character's inventory items in the order they were added to the Set by iterating through the
inventoryarray state variable.Renders a unordered list of the character's inventory by iterating through
character.inventory.
1 const TraverseCharacterInventory = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const [inventory, setInventory] = useState([]); 5 6 const character = useQuery( 7 Character, 8 characters => { 9 return characters.filtered(`name = '${characterName}'`); 10 }, 11 [characterName], 12 )[0]; 13 14 const addInventoryItem = () => { 15 realm.write(() => { 16 character?.inventory.add(inventoryItem); 17 }); 18 setInventory([...inventory, inventoryItem]); 19 }; 20 21 return ( 22 <View> 23 <Text>{character.name}</Text> 24 <Text>Add an item to the inventory:</Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Add Inventory Item' 31 onPress={addInventoryItem} 32 /> 33 34 <Text>Ordered Inventory:</Text> 35 {inventory.map(item => ( 36 <Text>{item}</Text> 37 ))} 38 39 <Text>Unordered Inventory:</Text> 40 {character.inventory.map(item => ( 41 <Text>{item}</Text> 42 ))} 43 </View> 44 ); 45 };
1 const TraverseCharacterInventory = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState<string>(''); 8 const [inventory, setInventory] = useState<string[]>([]); 9 10 const character = useQuery( 11 Character, 12 characters => { 13 return characters.filtered(`name = '${characterName}'`); 14 }, 15 [characterName], 16 )[0]; 17 18 const addInventoryItem = () => { 19 realm.write(() => { 20 character?.inventory.add(inventoryItem); 21 }); 22 setInventory([...inventory, inventoryItem]); 23 }; 24 25 return ( 26 <View> 27 <Text>{character.name}</Text> 28 <Text>Add an item to the inventory:</Text> 29 <TextInput 30 onChangeText={text => setInventoryItem(text)} 31 value={inventoryItem} 32 /> 33 <Button 34 title='Add Inventory Item' 35 onPress={addInventoryItem} 36 /> 37 38 <Text>Ordered Inventory:</Text> 39 {inventory.map(item => ( 40 <Text>{item}</Text> 41 ))} 42 43 <Text>Unordered Inventory:</Text> 44 {character.inventory.map(item => ( 45 <Text>{item}</Text> 46 ))} 47 </View> 48 ); 49 };