New in version realm@10.5.0.
You can use the Realm.Dictionary data type to
manage a collection of unique String keys paired with values. The dictionary
data maps to the Javascript Object type.
For example, creating a HomeOwner Realm object where the home property
is defined as a dictionary type could look like this:
realm.create('HomeOwner', { name: 'Anna Smith', home: {address: '2 jefferson lane', yearRenovated: 1994, color: 'blue'}, });
Realm Object Models
You can define a dictionary of mixed values for a Realm object model in three ways:
set the data type of your field to an empty object,
"{}".Add the data type before the brackets to create a dictionary with values of a specific type. For example,
"int{}"to specify that dictionary values must be integers or"string{}"to specify that dictionary values must be strings.Define the object type explicitly. This is necessary for using object Types in your Realm as ditionary values.
class HomeOwner extends Realm.Object { static schema = { name: 'HomeOwner', properties: { name: 'string', home: '{}', pets: { type: 'dictionary', objectType: 'Pet', optional: true, }, }, }; }
Use an interface that
extends the Realm.Dictionary type to define the syntax for your
dictionary object. All of your Realm Objects for this class must follow
the syntax specified in the interface.
interface Home extends Realm.Dictionary { address?: string; color?: string; price?: number; yearRenovated?: number; } class HomeOwner extends Realm.Object<HomeOwner> { name!: string; home!: Home; pets?: Pet[]; static schema: ObjectSchema = { name: 'HomeOwner', properties: { name: 'string', home: 'mixed{}', pets: { type: 'dictionary', objectType: 'Pet', optional: true, }, }, }; }
Realm disallows the use of . or $ characters in map keys.
You can use percent encoding and decoding to store a map key that contains
one of these disallowed characters.
// Percent encode . or $ characters to use them in map keys const mapKey = "kitchen.windows"; const encodedMapKey = mapKey.replace(".", "%2E");
Create an Object with a Dictionary Value
In the following CreateHomeOwner example, we create a new object with a dictionary property.
The CreateHomeOwner component does the following:
Create React state that represents the homeowner's name and address, respectively.
Get access to an open realm instance by calling the
useRealm()hook within the component.Create a component method
SubmitHomeOwner()that performs a write transaction and creates a newHomeOwnerobject based on theTextInputvalues for the homeowner's name and address, respectively.Add an onPress event on the submit button that calls
SubmitHomeOwner()
1 const CreateHomeOwner = () => { 2 const [homeOwnerName, setHomeOwnerName] = useState('John Smith'); 3 const [address, setAddress] = useState('1 Home Street'); 4 const realm = useRealm(); 5 6 const submitHomeOwner = () => { 7 // Create a HomeOwner realm object within a Write Transaction 8 realm.write(() => { 9 realm.create('HomeOwner', { 10 name: homeOwnerName, 11 // For the dictionary field, 'home', set the value 12 // to a regular JavaScript object 13 home: { 14 address, 15 }, 16 }); 17 }); 18 }; 19 return ( 20 <View> 21 <TextInput 22 value={homeOwnerName} 23 onChangeText={text => setHomeOwnerName(text)} 24 /> 25 <TextInput value={address} onChangeText={text => setAddress(text)} /> 26 <Button 27 title='Submit Home Owner' 28 onPress={submitHomeOwner} 29 /> 30 </View> 31 ); 32 };
Query for Objects with a Dictionary Property
To filter a query, run collection.filtered() to specify a subset of results based on the value(s) of one or more object properties. You can specify results based on the value of a dictionary's properties by using bracket notation.
You can also determine whether a results collection has a certain key or value
by using <dictionary>.@keys or <dictionary>.@values. For instance, if
you had a HomeOwner collection with a nested home dictionary, you could
return all HomeOwner objects with a home with a "price" property by
running the query: home.@keys = "price".
Example
In the following HomeList example, we query for objects that have dictionary properties.
The HomeList component does the following:
Performs a query for all homeowners by passing the
HomeOwnerclass to theuseQueryhook.Performs a query for homeowners with a listed price by passing
collection.filtered()the query:home.@keys = "price".Performs a query for the summer hill house by running
collection.filtered()using bracket notation to find the first homeowner with an address set to "Summerhill St." and getting their home by using dot syntax.Performs a query for all homeowners with any field with a value of red by passing
collection.filtered()the query:'home.@values = "red"'. We then get the first homeowner's home.Display the results of our queries in the UI by rendering information about the homes
1 const HomeList = () => { 2 // query for all HomeOwner objects 3 const homeOwners = useQuery(HomeOwner); 4 5 // run the `.filtered()` method on all the returned homeOwners to 6 // find all homeOwners that have a house with a listed price 7 const listedPriceHomes = useQuer(HomeOwner, homeOwners => { 8 return homeOwners.filtered('home.@keys = "price"'); 9 }); 10 11 // run the `.filtered()` method on all the returned homeOwners to 12 // find the house with the address "Summerhill St." 13 const summerHillHouse = useQuery(HomeOwner, homeOwners => { 14 return homeOwners.filtered('home["address"] = "Summerhill St."'); 15 })[0].home; 16 17 // run the `.filtered()` method on all the returned homeOwners to 18 // find the first house that has any field with a value of 'red' 19 const redHouse = useQuery(HomeOwner, homeOwners => { 20 return homeOwners.filtered('home.@values = "red"'); 21 })[0].home; 22 23 return ( 24 <View> 25 <Text>All homes:</Text> 26 {homeOwners.map(homeOwner => ( 27 <View> 28 <Text>{homeOwner.home.address}</Text> 29 </View> 30 ))} 31 32 <Text>All homes with a price:</Text> 33 {listedPriceHomes.map(homeOwner => ( 34 <View> 35 <Text>{homeOwner.home.address}</Text> 36 <Text>{homeOwner.home.price}</Text> 37 </View> 38 ))} 39 40 <Text>Summer Hill House:</Text> 41 <Text>{summerHillHouse.address}</Text> 42 <Text>{summerHillHouse.color}</Text> 43 44 <Text>Red House:</Text> 45 <Text>{redHouse.address}</Text> 46 </View> 47 ); 48 };
1 const HomeList = () => { 2 // query for all HomeOwner objects 3 const homeOwners = useQuery(HomeOwner); 4 5 // run the `.filtered()` method on all the returned homeOwners to 6 // find all homeOwners that have a house with a listed price 7 const listedPriceHomes = useQuery(HomeOwner, homeOwners => { 8 return homeOwners.filtered('home.@keys = "price"'); 9 }); 10 11 // run the `.filtered()` method on all the returned homeOwners to 12 // find the house with the address "Summerhill St." 13 const summerHillHouse = useQuery(HomeOwner, homeOwners => { 14 return homeOwners.filtered('home["address"] = "Summerhill St."'); 15 })[0].home; 16 17 // run the `.filtered()` method on all the returned homeOwners to 18 // find the first house that has any field with a value of 'red' 19 const redHouse = useQuery(HomeOwner, homeOwners => { 20 return homeOwners.filtered('home.@values = "red"'); 21 })[0].home; 22 23 return ( 24 <View> 25 <Text>All homes:</Text> 26 {homeOwners.map(homeOwner => ( 27 <View> 28 <Text>{homeOwner.home.address}</Text> 29 </View> 30 ))} 31 32 <Text>All homes with a price:</Text> 33 {listedPriceHomes.map(homeOwner => ( 34 <View> 35 <Text>{homeOwner.home.address}</Text> 36 <Text>{homeOwner.home.price}</Text> 37 </View> 38 ))} 39 40 <Text>Summer Hill House:</Text> 41 <Text>{summerHillHouse.address}</Text> 42 <Text>{summerHillHouse.color}</Text> 43 44 <Text>Red House:</Text> 45 <Text>{redHouse.address}</Text> 46 </View> 47 ); 48 };
Update a Dictionary
Update a dictionary's property by using the dictionary.set() method or dot notation to set its property to a new value.
Example
In the following UpdateHome example, we update a dictionary's property.
The UpdateHome component does the following:
- Create a React state
- variable that represents the home address.
- Get access to an opened realm instance by calling the
useRealm()hook - within the component.
- Get access to an opened realm instance by calling the
- Create a component method
updateAddress()that performs a write - transaction and uses
dictionary.set()to set the home's address to the value of theaddressstate variable. It also uses dot syntax to set theyearRenovatedto2004.
- Create a component method
Render a
TextInputthat displays and changes theaddressstate variable.- Add an onPress event on
- the "Update Address" button that calls
updateAddress()
1 const UpdateHome = ({homeOwnerName}) => { 2 const [address, setAddress] = useState(''); 3 const realm = useRealm(); 4 const homeOwner = useQuery( 5 HomeOwner, 6 homeOwners => { 7 return homeOwners.filtered(`name == '${homeOwnerName}'`); 8 }, 9 [homeOwnerName], 10 )[0]; 11 12 const updateAddress = () => { 13 // Update the home object with the new address 14 realm.write(() => { 15 // use the `set()` method to update a field of a dictionary 16 homeOwner.home.set({address}); 17 // alternatively, update a field of a dictionary through dot notation 18 homeOwner.home.yearRenovated = 2004; 19 }); 20 }; 21 22 return ( 23 <View> 24 <Text>{homeOwner.name}</Text> 25 <TextInput 26 value={address} 27 onChangeText={setAddress} 28 placeholder='Enter new address' 29 /> 30 <Button 31 onPress={updateAddress} 32 title='Update Address' 33 34 /> 35 </View> 36 ); 37 };
1 const UpdateHome = ({homeOwnerName}: {homeOwnerName: string}) => { 2 const [address, setAddress] = useState(''); 3 const realm = useRealm(); 4 const homeOwner = useQuery( 5 HomeOwner, 6 homeOwners => { 7 return homeOwners.filtered(`name == '${homeOwnerName}'`); 8 }, 9 [homeOwnerName], 10 )[0]; 11 12 const updateAddress = () => { 13 // Update the home object with the new address 14 realm.write(() => { 15 // use the `set()` method to update a field of a dictionary 16 homeOwner.home.set({address}); 17 // alternatively, update a field of a dictionary through dot notation 18 homeOwner.home.yearRenovated = 2004; 19 }); 20 }; 21 22 return ( 23 <View> 24 <Text>{homeOwner.name}</Text> 25 <TextInput 26 value={address} 27 onChangeText={setAddress} 28 placeholder='Enter new address' 29 /> 30 <Button 31 onPress={updateAddress} 32 title='Update Address' 33 /> 34 </View> 35 ); 36 };
Delete Members of a Dictionary
To delete members of a dictionary, use the dictionary.remove() method with an array of properties to remove from the dictionary.
Example
In the following HomeInfo example, we delete members of a dictionary.
The HomeInfo component does the following:
Get access to an open realm instance by calling the
useRealm()hook within the component.Retrieve the first homeowner that matches the name passed into the component as a prop. We do this by getting the first value returned from the query:
useQuery(HomeOwner).filtered(`name == '${homeOwnerName}'`).Create a component method
deleteExtraHomeInfo()that performs a write transaction and callsdictionary.remove()to remove theyearRenovatedandcolorproperties.Render the homeowner's name and home address in the UI.
Add an onPress event on the "Delete extra home info" button that calls
deleteExtraHomeInfo().
1 const HomeInfo = ({homeOwnerName}) => { 2 const realm = useRealm(); 3 const homeOwner = useQuery( 4 HomeOwner, 5 homeOwners => { 6 return homeOwners.filtered(`name == '${homeOwnerName}'`); 7 }, 8 [homeOwnerName], 9 )[0]; 10 11 const deleteExtraHomeInfo = () => { 12 realm.write(() => { 13 // remove the 'yearRenovated' and 'color' field of the house 14 homeOwner.home.remove(['yearRenovated', 'color']); 15 }); 16 }; 17 18 return ( 19 <View> 20 <Text>{homeOwner.name}</Text> 21 <Text>{homeOwner.home.address}</Text> 22 <Button 23 onPress={deleteExtraHomeInfo} 24 title='Delete extra home info' 25 26 /> 27 </View> 28 ); 29 };
1 const HomeInfo = ({homeOwnerName}: {homeOwnerName: string}) => { 2 const realm = useRealm(); 3 const homeOwner = useQuery( 4 HomeOwner, 5 homeOwners => { 6 return homeOwners.filtered(`name == '${homeOwnerName}'`); 7 }, 8 [homeOwnerName], 9 )[0]; 10 11 const deleteExtraHomeInfo = () => { 12 realm.write(() => { 13 // remove the 'yearRenovated' and 'color' field of the house 14 homeOwner.home.remove(['yearRenovated', 'color']); 15 }); 16 }; 17 18 return ( 19 <View> 20 <Text>{homeOwner.name}</Text> 21 <Text>{homeOwner.home.address}</Text> 22 <Button 23 onPress={deleteExtraHomeInfo} 24 title='Delete extra home info' 25 /> 26 </View> 27 ); 28 };